Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.
Traversing Strings with Pointers
Walk a C string with an index or a pointer, write your own length function and print text backwards safely.
What You Will Learn
- What string traversal in C means and why loops end on the NUL byte
- Two ways to walk a string: with an index and with a pointer
- How pointer increment and pointer subtraction work on a char array
- How to write your own string length function in four lines
- How to walk a string backwards without running off the start
- The mistakes that make string loops slow, wrong or unsafe
Prerequisites
- Lecture 4: string variables and sizing
- Pointer arithmetic from the Pointers chapter
forandwhileloops
Every useful string operation, from counting letters to parsing a UART command, begins with string traversal in C: stepping through the characters until the terminator appears. In this lecture of the free C programming course you will traverse a string with an index and with a pointer, write your own length function, and learn the pointer rules that make it all safe. These are core skills for embedded C programming, where small, fast loops over text and byte buffers are everywhere.
String Traversal in C: The Sentinel Loop
When you loop over an ordinary array you usually know how many elements it has. With a string you do not, so the loop watches for a sentinel: the zero byte. The loop body runs for every character and the loop ends as soon as it reads the terminator. The terminator itself is never processed as text.
| Loop style | Stops when | Needs the length first? | Typical use |
|---|---|---|---|
Counted: for (i = 0; i < n; i++) | i reaches n | Yes | Raw byte buffers |
Sentinel: while (*p != '\0') | terminator is read | No | C strings |
The string sensor with an index and a moving pointer
| Index i | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| Character | s | e | n | s | o | r | \0 |
| Pointer offset p – word | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| Loop action | visit | visit | visit | visit | visit | visit | stop |
Index i and the pointer offset are the same number: word[i] and *(word + i) name the same byte. Choosing between them is a matter of style, not of meaning.
Traverse a String With an Index and With a Pointer
Save this as string_walk.c. It walks the same word both ways, measures its length with a hand-made function, prints it backwards, and shows how far apart two neighbouring characters are in memory.
#include <stdio.h>
static size_t ep_len(const char *s)
{
const char *p = s;
while (*p != '\0')
p++;
return (size_t)(p - s);
}
int main(void)
{
char word[] = "sensor";
puts("-- index loop --");
for (size_t i = 0; word[i] != '\0'; i++)
printf("word[%zu] = '%c'\n", i, word[i]);
puts("-- pointer loop --");
for (const char *p = word; *p; p++)
printf("offset %td -> '%c'\n", p - word, *p);
printf("length : %zu\n", ep_len(word));
const char *end = word + ep_len(word);
printf("reversed: ");
while (end > word)
putchar(*--end);
putchar('\n');
printf("gap between word[0] and word[1]: %td byte\n",
(char *)&word[1] - (char *)&word[0]);
printf("base address (varies per run) : %p\n", (void *)word);
return 0;
}
gcc -std=c17 -Wall -Wextra -o string_walk string_walk.c
./string_walk
Expected output (the last address will differ on your machine, which is normal):
-- index loop --
word[0] = 's'
word[1] = 'e'
word[2] = 'n'
word[3] = 's'
word[4] = 'o'
word[5] = 'r'
-- pointer loop --
offset 0 -> 's'
offset 1 -> 'e'
offset 2 -> 'n'
offset 3 -> 's'
offset 4 -> 'o'
offset 5 -> 'r'
length : 6
reversed: rosnes
gap between word[0] and word[1]: 1 byte
base address (varies per run) : 0x7ffd560955e1
How the Pointer Loop Works
In for (const char *p = word; *p; p++) the pointer starts at the first character. The test *p is true for any non-zero byte and false for the terminator, so it is a compact way to write *p != '\0'. Each pass the pointer moves one element forward. Because the element type is char, one step is exactly one byte.
One pass of the pointer loop
The offset printed with %td is p - word. Subtracting two pointers into the same array gives the number of elements between them, as a ptrdiff_t, which is why the format letter is td. Indexes and lengths use size_t with %zu.
Write Your Own String Length Function
The helper ep_len shows the idea in four lines: remember where the string starts, advance a second pointer to the terminator, and subtract. It returns 6 for "sensor", exactly what the library strlen would. In production code use strlen, because the library version is heavily optimised, but writing it once cements how pointers and terminators cooperate.
Walking Backwards Safely
To print the word in reverse, the program sets end to the terminator’s address and uses *--end. The pointer is decremented before it is read, so the terminator is never printed, and the loop condition end > word stops it before it moves in front of the array. Pointing one past the end of an array is allowed; pointing before the start is not.
Index Versus Pointer: Which to Choose
| Aspect | Index s[i] | Pointer *p |
|---|---|---|
| Reads most clearly when | you need the position | you only need the next character |
| Position available? | Yes, it is i | Only through p - s |
| Common in | application code | library and driver code |
| Generated code | similar | similar |
| Risk | off-by-one in the bound | running before or past the buffer |
Real-World Uses of String Traversal
GPS sentence checksums
A GPS module sends text lines whose checksum is the XOR of every character between two markers, computed by walking the string.
Command tokenising
A serial console walks the line to find spaces and split command and arguments.
Display drivers
A text LCD driver writes one character per iteration until the terminator.
Input validation
Check that a string contains only digits before converting it to a number.
Common Mistakes When You Traverse a String
| Mistake | Effect | Fix |
|---|---|---|
Looping with i <= length | Processes the terminator as text | Use < or test for '\0' |
Looping up to sizeof | Visits unused bytes beyond the text | Stop at the terminator |
strlen in the loop condition | Quadratic slowdown | Compute once |
| Decrementing past the start | Undefined behaviour | Compare against the start pointer first |
Printing an address with %u | Wrong or truncated value | Use %p and a void * cast |
Best Practices, Performance and Security
- Use
const char *for walkers that only read the text, so the compiler enforces it. - Use
size_tfor indexes and lengths, never a plainintwhen the string might be long. - Performance: a string of 1000 characters walked with
strlenin the condition performs roughly half a million character reads; one stored length needs 1000. - Security: text from a UART or network may lack a terminator. When the source is untrusted, pass the buffer size and stop at whichever comes first, the terminator or the limit.
Summary and Key Takeaways
- String traversal ends at the terminator because C strings do not store a length.
s[i]and*(s + i)are the same; a char pointer moves one byte per increment.- Subtracting two pointers into one array gives the element count.
- Never go before the start of the array; one past the end is legal to point at but not to read.
With traversal in your toolbox, you are ready for the practical side of strings: reading text from the keyboard or a serial port and printing it back. That is the subject of the next lecture of this free embedded C course, where scanf, printf and fgets get a careful look.
Frequently Asked Questions
What is string traversal in C?
String traversal means visiting the characters of a string one after another, from the first byte to the terminating zero. You can do it with an index (s[i]) or with a pointer that you increment.
Why does the loop test for ‘\0’ instead of a count?
A C string does not store its length. The terminator is the only reliable marker, so loops written as while (*p != '\0') work for any string without knowing its size in advance.
Is it faster to traverse with a pointer or with an index?
On a modern optimising compiler they generate essentially the same machine code. Pick the form that reads better. Pointer style is common in library code, index style is often clearer in application code.
What does subtracting two char pointers give?
The number of elements between them, with type ptrdiff_t. For char pointers that equals the number of bytes. It is the idea behind a hand-written length function: end pointer minus start pointer.
Why should I not call strlen in the loop condition?
strlen scans the whole string every time it is called. In for (i = 0; i < strlen(s); i++) that makes the loop quadratic. Call it once before the loop, or test for the terminator directly.
How do I print a pointer value correctly?
Cast it to void * and use %p. Printing an address with %u, as older textbooks do, truncates it on 64-bit systems and is undefined behaviour. The value also changes between runs because of address space randomisation.
Topics Covered in This Lecture
Keep Going With the Free C Programming Course
EmbeddedPathashala teaches C from the first printf to embedded-ready pointers and strings, completely free. Next: reading and printing strings with scanf, printf and fgets.
Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments