Pointers & Strings
C has no built-in string type — a string is just a char array terminated by a \\0 byte, and strings are one of the places where pointers show up constantly in everyday code. This page focuses on one specific, classic gotcha: the difference between a pointer to a string literal and a real, modifiable array copy of one.
What a string literal actually is
When you write "hello" in your source code, the compiler stores those characters (plus a terminating \\0) somewhere in the program's memory, and the literal itself, when used as a value, gives you a char * pointing at the first character.
#include <stdio.h>
int main(void) {
char *s = "hello"; // s points at the literal's first character
printf("s = %s\n", s);
printf("s[0] = %c\n", s[0]);
printf("*(s+1) = %c\n", *(s + 1));
return 0;
}s = hello s[0] = h *(s+1) = e
char *s vs. char s[] — a critical difference
These two declarations look similar but behave very differently, and confusing them is one of the most common bugs new C programmers write:
char *s1 = "hello"; // s1 points to a string literal char s2[] = "hello"; // s2 is a genuine, modifiable array copy
s2 is a local array, initialized by copying the letters h, e, l, l, o, \\0 into its own storage on the stack. Modifying s2[0] is completely safe. s1, on the other hand, is just a pointer aimed at the literal "hello" itself, which many compilers place in read-only memory. Writing through s1 is undefined behavior.
#include <stdio.h>
int main(void) {
char *s1 = "hello";
// s1[0] = 'H'; // UNDEFINED BEHAVIOR — often crashes: literal is read-only
char s2[] = "hello";
s2[0] = 'H'; // OK — s2 is a real, modifiable array
printf("%s\n", s2);
return 0;
}Hello
Iterating a string with pointer arithmetic
Because a string is just a char array ending in \\0, an idiomatic (if slightly old-school) way to walk through it is to advance a pointer until it reaches the terminator, rather than indexing with [i]:
#include <stdio.h>
int main(void) {
char s[] = "pointer";
int count = 0;
for (char *p = s; *p != '\0'; p++) {
count++;
}
printf("length of \"%s\" is %d\n", s, count);
return 0;
}length of "pointer" is 7
"hello"as a value is achar *pointing at storage the compiler set up for the literal — often read-only.char *s = "hello";points at that literal; writing throughsis undefined behavior.char s[] = "hello";copies the characters into a fresh, modifiable local array — safe to write to.Walking a string by advancing a
char *pointer until it hits\0is a classic, idiomatic C pattern.