Last 30 Days
No notifications
C has no built-in string type. A "string" in C is simply a char array that ends with a special null terminator '\0'.
char name[6] = {'R', 'a', 'h', 'u', 'l', '\0'};
char name2[] = "Rahul"; // same thing ā compiler adds '\0' for youMemory layout:
[ 'R' ][ 'a' ][ 'h' ][ 'u' ][ 'l' ][ '\0' ]
0 1 2 3 4 5The '\0' is not the digit '0' (which is 48). It's the byte with value 0 ā it tells every C function "the string ends here".
char a[] = "Hello"; // size auto = 6 (5 chars + '\0')
char b[20] = "Hi"; // 20 bytes, only first 3 used
char *c = "World"; // pointer to read-only string literal> ā ļø Strings created with char *c = "..." are read-only. Modifying c[0] = 'X'; is undefined behaviour (often a crash).
char buf[100];
scanf("%s", buf); // ā ļø unsafe ā can overflow
scanf("%99s", buf); // ā
caps input length
fgets(buf, sizeof(buf), stdin); // ā
best ā reads whole line including spaces)| Function | Purpose |
strlen(s) | Length (excludes '\0') |
strcpy(dst, src) | Copy string |
strcat(dst, src) | Append src to dst |
strcmp(a, b) | Compare; 0 = equal, <0 = a0 = a>b |
strchr(s, c) | Find first occurrence of char c |
strstr(haystack, needle) | Find substring |
Strings in C are deceptively simple ā and that simplicity is the source of an entire category of security bugs that have plagued software for 50 years.
Look at strlen:
size_t strlen(const char *s) {
size_t n = 0;
while (s[n] != '\0') n++; // count bytes until we hit '\0'
return n;
}Without '\0', strlen would have no way to know where the string ends. Every standard C string function relies on this terminator.
If you forget to put '\0' at the end of a char array, strlen will keep walking past your array ā possibly reading hundreds of bytes that aren't yours, until it accidentally finds a zero byte. That's the famous buffer over-read bug (Heartbleed was exactly this).
char s[] = "Hello";
printf("%zu\n", sizeof(s)); // 6 ā 'H' 'e' 'l' 'l' 'o' '\0'
printf("%zu\n", strlen(s)); // 5 ā strlen does NOT count '\0'Always remember: a string of N characters needs N + 1 bytes of storage.
char *p = "Hello"; // p points to a string literal in READ-ONLY memory
char q[] = "Hello"; // q is a writable copy on the stackp[0] = 'X'; // ā undefined behaviour ā usually crashes
q[0] = 'X'; // ā
fine ā q is now "Xello"
char *p = "Hi" | char q[] = "Hi" | |
| Where stored | Read-only data segment | Stack (writable) |
| Modifiable? | ā No | ā Yes |
| Can be reassigned? | ā
p = "Bye"; | ā Array name is constant |
char small[5];
strcpy(small, "Hello, World"); // ā writes 13 bytes into 5 ā buffer overflow!strcpy doesn't check the destination size. It will happily write past the end, corrupting whatever comes after ā possibly your return address, which is how attackers used to take over programs.
Safer alternatives:
char dst[10];
snprintf(dst, sizeof(dst), "%s", src); // ā
truncates safely
strncpy(dst, src, sizeof(dst) - 1); // ā ļø doesn't always null-terminate
dst[sizeof(dst) - 1] = '\0'; // so add thisModern advice: prefer snprintf over strcpy and strcat for any production code.
char name[10];
scanf("%s", name); // ā if user types 50 chars, BOOMUse a width specifier or fgets:
scanf("%9s", name); // ā
reads at most 9 chars
fgets(name, sizeof(name), stdin); // ā
reads a full linefgets includes the trailing '\n' if the line fits ā strip it:
size_t len = strlen(name);
if (len > 0 && name[len-1] == '\n') name[len-1] = '\0';strcmp("apple", "banana") // negative (apple < banana alphabetically)
strcmp("hi", "hi") // 0
strcmp("zoo", "ant") // positiveReturns the difference of the first non-matching characters. Never use == to compare strings ā that compares pointers:
if (a == b) // ā compares ADDRESSES
if (strcmp(a, b) == 0) // ā
compares CONTENTchar buf[100] = "Hello";
strcat(buf, ", ");
strcat(buf, "World");
strcat(buf, "!");Each strcat walks the string from the start to find '\0' ā so building a long string with many strcats is O(n²). For heavy concatenation, track a position pointer or use snprintf once.
char s[] = "Hello, World";strlen(s); // 12
strchr(s, 'W'); // pointer to "World"
strstr(s, "World"); // pointer to "World"
strcmp(s, "Hello"); // > 0
char copy[20]; strcpy(copy, s);
/* Convert case manually */
for (int i = 0; s[i]; i++) {
if (s[i] >= 'a' && s[i] <= 'z') s[i] -= 32; // ā uppercase
}
/* Reverse in place */
int n = strlen(s);
for (int i = 0, j = n - 1; i < j; i++, j--) {
char t = s[i]; s[i] = s[j]; s[j] = t;
}
| Mistake | Result |
Forgot '\0' | Functions read past your array |
Wrote to char * literal | Crash or undefined |
Used strcpy to small buffer | Buffer overflow |
Compared with == | Compared addresses, not text |
Used scanf("%s") without width | Stack smash if input too long |
Strings are the place where C beginners learn (the hard way) why memory safety matters.