Nested Loop Examples in Embedded C: Search, Primes, Patterns, Matrices, Frames and Glyphs-Free Embedded Course Online

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

MODULE 7 · LESSON 7.3 · EXAMPLES

Nested Loop Examples in Embedded C: Search, Primes, Patterns, Matrices, Frames and Glyphs

Eight worked examples with real output: linear search, primes with break, triangle/pyramid/diamond patterns, 3×3 matrices, frame extraction, sensor filtering with continue, a 5×7 dot-matrix glyph and a pair-sum search. Study this one of the nested loop examples in embedded C closely.

9
Worked Examples
Intermediate
Level
Real output
Compiled and run

Nested Loop Examples in Embedded C: What This Page Covers

These nested loop examples in embedded C combine break, continue and loops inside loops into practical routines: searching tables, finding primes, drawing patterns, handling matrices, extracting frames, filtering sensor data and rendering a 5×7 dot-matrix glyph. All programs were compiled and run with GCC; the output shown is real. These nested loop examples in embedded C build on each other.

#ExampleSkill
1Linear search with break and a comparison countEarly exit
2Prime numbers with an early-exit inner loopNested break
3Triangle, pyramid and diamond patternsNested for
43×3 matrix add, transpose and multiplyTriple nesting
5Extracting frames between start and end markersbreak/continue
6Filtering invalid sensor datacontinue
7Rendering a 5×7 font glyph for an LED matrixBits in nested loops
8Finding a pair that adds up to a targetLeaving two loops
9Mini exercisesSelf-test

Example 1: Linear Search with Early Exit

Problem: Find a value in an unsorted table and report how much work was done. The loop stops at the first match; a miss costs all n comparisons. On average a successful search examines half the table. Among the nested loop examples in embedded C this pattern is very common.

linear_search.c
#include <stdio.h> static int linear_search(const int *a, int n, int key, int *compares) { *compares = 0; for (int i = 0; i < n; i++) { (*compares)++; if (a[i] == key) return i; /* early exit: found */ } return –1; } int main(void) { int a[] = { 31, 4, 15, 9, 26, 5, 35, 8 }; int n = sizeof a / sizeof a[0]; int keys[] = { 31, 26, 8, 99 }; for (int k = 0; k < 4; k++) { int c; int pos = linear_search(a, n, keys[k], &c); if (pos >= 0) printf(“key %2d found at index %d after %d comparisons\n”, keys[k], pos, c); else printf(“key %2d not found after %d comparisons\n”, keys[k], c); } return 0; }
Output (verified by compiling and running)
key 31 found at index 0 after 1 comparisons key 26 found at index 4 after 5 comparisons key 8 found at index 7 after 8 comparisons key 99 not found after 8 comparisons
Faster searches: For sorted data use binary search (about log₂ n comparisons). For lookups by key in firmware, a hash table or a direct index table (table[key]) usually beats searching.

Example 2: Prime Numbers with an Early-Exit Inner Loop

Problem: List the primes up to 50. The outer loop takes each candidate; the inner loop tries divisors and leaves with break as soon as one divides evenly. The limit d * d <= n stops at the square root, so the number of divisions stays small. Keep these nested loop examples in embedded C for revision.

primes.c
#include <stdio.h> int main(void) { int checks = 0; printf(“primes up to 50:”); for (int n = 2; n <= 50; n++) { int is_prime = 1; for (int d = 2; d * d <= n; d++) /* only divisors up to sqrt(n) */ { checks++; if (n % d == 0) { is_prime = 0; break; /* one divisor is enough */ } } if (is_prime) printf(” %d”, n); } printf(“\ndivisions performed: %d\n”, checks); return 0; }
Output (verified by compiling and running)
primes up to 50: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 divisions performed: 95

A naive version that tries every divisor from 2 to n − 1 and never leaves early performs 1176 divisions for this range; the two improvements together reduce the work to the 95 divisions shown above.

Example 3: Triangle, Pyramid and Diamond

Problem: Draw shapes with nested loops. Each row needs leading spaces and a number of stars that depends on the row number: the inner limits are expressions of the outer counter. The same technique draws bar graphs on a character LCD or serial terminal.

patterns.c
#include <stdio.h> int main(void) { int n = 4; printf(“right triangle\n”); for (int row = 1; row <= n; row++) { for (int c = 0; c < row; c++) putchar(‘*’); putchar(‘\n’); } printf(“pyramid\n”); for (int row = 1; row <= n; row++) { for (int s = 0; s < n – row; s++) putchar(‘ ‘); for (int c = 0; c < 2 * row – 1; c++) putchar(‘*’); putchar(‘\n’); } printf(“diamond\n”); for (int row = -(n – 1); row <= n – 1; row++) { int width = n – (row < 0 ? -row : row); /* distance from the middle */ for (int s = 0; s < n – width; s++) putchar(‘ ‘); for (int c = 0; c < 2 * width – 1; c++) putchar(‘*’); putchar(‘\n’); } return 0; }
Output (verified by compiling and running)
right triangle * ** *** **** pyramid * *** ***** ******* diamond * *** ***** ******* ***** *** *
ShapeSpaces in row rStars in row r
Right triangle0r
Pyramid (n rows)n − r2r − 1
Diamond (distance d from the middle)d2(n − d) − 1

Example 4: 3×3 Matrix Addition, Transpose and Multiplication

Problem: Matrix arithmetic appears in sensor fusion, coordinate rotation and filters. Addition and transposition need two nested loops; multiplication needs three, so the cost grows as N³ (27 multiplications here). The row-by-row walk keeps the column index in the inner loop where possible.

matrix.c
#include <stdio.h> #define N 3 static void print_m(const char *name, int m[N][N]) { printf(“%s\n”, name); for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) printf(“%4d”, m[r][c]); printf(“\n”); } } int main(void) { int a[N][N] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; int b[N][N] = { { 9, 8, 7 }, { 6, 5, 4 }, { 3, 2, 1 } }; int sum[N][N], tr[N][N], prod[N][N]; for (int r = 0; r < N; r++) for (int c = 0; c < N; c++) { sum[r][c] = a[r][c] + b[r][c]; tr[c][r] = a[r][c]; } for (int r = 0; r < N; r++) for (int c = 0; c < N; c++) { int acc = 0; for (int k = 0; k < N; k++) /* triple nesting: 3 x 3 x 3 = 27 multiplies */ acc += a[r][k] * b[k][c]; prod[r][c] = acc; } print_m(“A + B”, sum); print_m(“transpose of A”, tr); print_m(“A x B”, prod); return 0; }
Output (verified by compiling and running)
A + B 10 10 10 10 10 10 10 10 10 transpose of A 1 4 7 2 5 8 3 6 9 A x B 30 24 18 84 69 54 138 114 90
Embedded note: For larger matrices use the CMSIS-DSP functions arm_mat_mult_f32() or the fixed-point variants; they use the Cortex-M4 DSP instructions and the FPU.

Example 5: Extracting Frames Between Start and End Markers

Problem: A serial link delivers text frames wrapped in STX (0x02) and ETX (0x03) with line noise in between. Each continue handles one case and returns to the loop top, so the code stays flat: start byte, noise outside a frame, end byte, data byte. A new STX inside a frame discards the broken one.

frame_extract.c
#include <stdio.h> #include <stdint.h> #define STX 0x02 #define ETX 0x03 int main(void) { /* noise, a frame, noise with a stray byte, a frame with a missing ETX followed by a new STX, then a good frame */ uint8_t rx[] = { 0x55, STX, ‘O’, ‘N’, ETX, 0x00, 0xFF, STX, ‘A’, ‘B’, STX, ‘O’, ‘F’, ‘F’, ETX, 0x7F }; unsigned n = sizeof rx; char frame[8]; unsigned len = 0; int in_frame = 0; for (unsigned i = 0; i < n; i++) { uint8_t b = rx[i]; if (b == STX) /* start (or restart after a broken frame) */ { in_frame = 1; len = 0; continue; } if (!in_frame) /* outside a frame: ignore noise */ continue; if (b == ETX) /* complete frame */ { frame[len] = ‘\0’; printf(“frame: \”%s\” (%u chars)\n”, frame, len); in_frame = 0; continue; } if (len < sizeof frame – 1) frame[len++] = (char)b; } return 0; }
Output (verified by compiling and running)
frame: “ON” (2 chars) frame: “OFF” (3 chars)

The output shows two frames. The broken frame “AB” is dropped when the next STX arrives, which is the standard way to resynchronise.

Example 6: Filtering Invalid Sensor Data with continue

Problem: A 12-bit ADC returns 0 for an open input and 4095 for a short or saturation; anything above 4095 is a software error. Skip such samples and compute statistics from the rest. The continue keeps the three calculations at one indentation level.

filter_samples.c
#include <stdio.h> #define INVALID 4095 int main(void) { int raw[] = { 2048, 2050, INVALID, 1990, 0, 2110, 2051, 5000, 2049 }; int n = sizeof raw / sizeof raw[0]; int count = 0, rejected = 0; long sum = 0; int min = 4096, max = –1; for (int i = 0; i < n; i++) { int v = raw[i]; if (v <= 0 || v >= INVALID) /* open, shorted or out of range */ { rejected++; continue; } if (v < min) min = v; if (v > max) max = v; sum += v; count++; } printf(“samples=%d valid=%d rejected=%d\n”, n, count, rejected); printf(“min=%d max=%d mean=%ld\n”, min, max, sum / count); return 0; }
Output (verified by compiling and running)
samples=9 valid=6 rejected=3 min=1990 max=2110 mean=2049
Division by zero: If every sample were rejected, count would be 0 and sum / count would crash. Production code checks count > 0 before dividing.

Example 7: Rendering a 5×7 Font Glyph

Problem: Character LCD modules and LED matrices store each character as seven bytes with five useful bits each. The outer loop walks the seven rows, the inner loop walks the five pixels from the leftmost bit (bit 4) to the rightmost (bit 0). On real hardware the inner loop would set an output pin instead of printing a character.

glyph.c
#include <stdio.h> #include <stdint.h> /* 5×7 glyphs for the digits 0, 1 and 5: 7 rows, each row is 5 bits (bit 4 = leftmost pixel) */ static const uint8_t glyph[3][7] = { { 0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E }, /* 0 */ { 0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E }, /* 1 */ { 0x1F, 0x10, 0x1E, 0x01, 0x01, 0x11, 0x0E }, /* 5 */ }; int main(void) { const char *names = “015”; for (int g = 0; g < 3; g++) { printf(“digit %c\n”, names[g]); for (int row = 0; row < 7; row++) { for (int col = 4; col >= 0; col–) /* leftmost pixel is bit 4 */ putchar((glyph[g][row] >> col) & 1u ? ‘#’ : ‘.’); putchar(‘\n’); } } return 0; }
Output (verified by compiling and running)
digit 0 .###. #…# #..## #.#.# ##..# #…# .###. digit 1 ..#.. .##.. ..#.. ..#.. ..#.. ..#.. .###. digit 5 ##### #…. ####. ….# ….# #…# .###.

A 64-character font needs only 64 × 7 = 448 bytes of flash. The same nested loops can be used to send a bitmap to an SPI display, one row at a time.

Example 8: Finding a Pair That Adds Up to a Target

Problem: Find two readings whose sum equals a target (for example to check a calibration pair). The inner loop starts at i + 1, so each pair is examined once. A break leaves the inner loop and the extra test fi < 0 in the outer condition stops the outer loop: the flag technique from the theory page.

pair_sum.c
#include <stdio.h> int main(void) { int a[] = { 8, 3, 11, 5, 2, 9 }; int n = sizeof a / sizeof a[0]; int target = 14; int fi = –1, fj = –1; for (int i = 0; i < n && fi < 0; i++) { for (int j = i + 1; j < n; j++) { if (a[i] + a[j] == target) { fi = i; fj = j; break; /* leaves the inner loop; the outer test sees fi >= 0 */ } } } if (fi >= 0) printf(“%d + %d = %d at indexes %d and %d\n”, a[fi], a[fj], target, fi, fj); else printf(“no pair adds up to %d\n”, target); int count = 0; for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) count++; printf(“a full scan would examine %d pairs\n”, count); return 0; }
Output (verified by compiling and running)
3 + 11 = 14 at indexes 1 and 2 a full scan would examine 15 pairs

Pairs are examined in index order, so 3 + 11 at indexes 1 and 2 is reported first. The pair 5 + 9 also adds up to 14, but it is never reached because both loops have already stopped. If you need all pairs, remove the early exit.

Example 9: Mini Exercises

Exercise 1: How many times does the inner body run in for (i = 0; i < 4; i++) for (j = 0; j < 3; j++)?
12 times.
Exercise 2: And in for (i = 0; i < 4; i++) for (j = 0; j < i; j++)?
0 + 1 + 2 + 3 = 6 times.
Exercise 3: Which statement skips only the current pass of a loop?
continue.
Exercise 4: In Example 2, why is d * d <= n enough?
If n has a divisor larger than its square root, it also has a smaller one, which the loop finds first.
Exercise 5: How can you leave two nested loops without goto?
Use a flag in both conditions, or put the loops in a function and return.
Exercise 6: What is the cost class of matrix multiplication with three loops?
N cubed.
Exercise 7: Why does Example 5 use continue after setting in_frame?
The STX byte itself must not be stored as data; continue goes to the next byte.

Key Takeaways from the Nested Loop Examples in Embedded C

  • These nested loop examples in embedded C show that the inner limit often depends on the outer counter.
  • break gives the early exit that makes searches cheap; continue keeps filtering code flat.
  • Nested loop cost multiplies: matrix multiplication is cubic, a pair search quadratic.
  • Leave two loops with a flag in the outer condition, or move the loops to a function.
  • Bitmaps and fonts are processed by nested loops over rows and bits.
  • Always guard divisions and array indexes that depend on how many items were accepted.

Ready for the quiz?

Next: predict the output of loops with break and continue, find the bugs and answer the interview questions.

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *