Strings
C has no built-in string type. A "string" is just an array of char with one special rule: it ends with a hidden '\0' byte, the null terminator, which is how every string function knows where the text stops.
Declaring and printing a string
#include <stdio.h> int main(void) { char name[] = "Maya"; printf("Hello, %s!\n", name); printf("First letter: %c\n", name[0]); return 0; }
Hello, Maya! First letter: M
char name[] = "Maya" actually allocates 5 bytes, not 4 — 'M', 'a', 'y', 'a', and a trailing '\0' the compiler adds for you. %s in printf prints characters starting at name and keeps going until it hits that '\0'.
printf) will keep reading into whatever memory happens to follow, printing garbage or crashing.Common string.h functions
The <string.h> header covers most day-to-day string work: length, copying, comparing, and joining:
#include <stdio.h> #include <string.h> int main(void) { char greeting[32] = "Hello"; printf("Length: %zu\n", strlen(greeting)); strcat(greeting, ", world"); printf("After strcat: %s\n", greeting); printf("Compare: %d\n", strcmp("abc", "abd")); return 0; }
Length: 5 After strcat: Hello, world Compare: -1
strlen counts characters up to (but not including) the null terminator. strcat appends one string onto the end of another, in place — which is why greeting had to be declared with 32 bytes of room, far more than "Hello" needs, to leave space for what gets tacked on later. strcmp returns 0 for equal strings, and a negative or positive number depending on which string sorts first alphabetically — here 'c' comes before 'd', so it returns a negative value.
Copying strings safely
strcpy copies one string into another buffer, but like strcat, it has no idea how big the destination buffer actually is — it will happily write past the end of it. strncpy takes an explicit size limit and is the safer default:
#include <stdio.h> #include <string.h> int main(void) { char dest[8]; strncpy(dest, "Copy me", sizeof(dest) - 1); dest[sizeof(dest) - 1] = '\0'; printf("%s\n", dest); return 0; }
Copy me
Reserving one byte for the terminator (sizeof(dest) - 1) and then setting it explicitly afterward is a defensive habit worth keeping: strncpy will not add a null terminator itself if the source string is exactly as long as the limit you gave it, leaving dest without one and every later %s read running off the end.