Describe the picture

In Python or Java, text is easy: you write name = "Ann" and the language takes care of everything.

C is different. C has no string type at all. Text is stored in an ordinary array of char — with one small but very important extra character at the end.

Understanding that extra character explains most of the strange string bugs beginners run into.

A string is a char array

Each character in C is one char, which takes one byte and holds the character's code (for example, 'A' is 65 in ASCII).

So the word Hi could be stored like this:

char word[3] = {'H', 'i', '\0'};

That third character, '\0', is the null character — the byte with value 0. It marks where the text ends.

Because typing characters one by one is tedious, C lets you write the same thing with a string literal:

char word[] = "Hi";

The compiler adds the '\0' for you, so word is 3 bytes, not 2.

Index 0 1 2
Character 'H' 'i' '\0'
Byte value 72 105 0

Why does C need the '\0'?

When you pass an array to a function, the function only receives the address of the first character. It has no idea how long the array is.

So how does printf("%s", word) know when to stop printing?

It prints character after character until it finds '\0'. The terminator is the only thing that tells it "the text ends here".

strlen works the same way: it counts characters until it reaches '\0'. You could write it yourself:

int myStrlen(const char s[])
{
    int n = 0;
    while (s[n] != '\0')
        n++;
    return n;
}

Length vs size: a classic exam question

char s[] = "Hello";
printf("%zu %zu\n", strlen(s), sizeof s);

Output:

5 6
  • strlen(s) is 5 — the characters before '\0'.
  • sizeof s is 6 — every byte of the array, terminator included.

Rule: an array that holds a word of n letters needs at least n + 1 cells.

What happens without the '\0'?

char s[5] = {'H', 'e', 'l', 'l', 'o'};   // no room for '\0'
printf("%s\n", s);

This is not a string. printf prints Hello and then keeps going into whatever memory comes next, until it happens to find a zero byte. You may see Hello followed by strange symbols — or the program may crash.

The same thing happens if you write

char s[5] = "Hello";   // 5 letters, and the '\0' does not fit

Always leave room for the terminator: char s[6] = "Hello"; or simply char s[] = "Hello";.

A '\0' in the middle cuts the string

Since everything stops at the first '\0', you can shorten a string by writing one:

char s[] = "Hello";
s[2] = '\0';
printf("%s\n", s);   // He

The letters llo are still in memory, but no string function will ever look at them.

Reading text: scanf vs fgets

Suppose a user types their full name: Ada Lovelace.

char name[30];
scanf("%29s", name);
printf("[%s]\n", name);

Output:

[Ada]

%s stops at the first space. The rest (Lovelace and the Enter key) stays in the input buffer and will confuse your next scanf.

Notice two details:

  • There is no & before name: an array name already is an address.
  • %29s limits the input to 29 characters, leaving room for '\0'. Without a limit, a long input would overflow the array.

To read a whole line, use fgets:

char name[30];
fgets(name, sizeof name, stdin);
printf("[%s]\n", name);

Output:

[Ada Lovelace
]

fgets reads spaces too, and it never writes past the end of the array. But it keeps the newline ('\n') from the Enter key — that is why the ] moved to the next line. Remove it like this:

#include <string.h>

name[strcspn(name, "\n")] = '\0';

strcspn finds the position of the first '\n', and we replace it with the terminator.

Never use gets(). It has no size limit at all, which made it so dangerous that it was removed from the C language.

You cannot assign or compare strings with = and ==

These two lines look reasonable but are wrong:

char a[20];
a = "hello";                 // error: arrays cannot be assigned

if (answer == "yes") { }     // compares two ADDRESSES, never the text

Use the functions from <string.h> instead:

strcpy(a, "hello");               // copy text into the array

if (strcmp(answer, "yes") == 0)   // 0 means "equal"
{
    printf("Great!\n");
}

Just remember that strcpy and strcat do not check the size of the destination. Make sure the array is big enough, or the copy will overwrite other memory (a buffer overflow).

Walking through a string

You do not need the length to loop over a string — just stop at '\0':

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char s[] = "c lab 2026";

    for (int i = 0; s[i] != '\0'; i++)
        s[i] = toupper(s[i]);

    printf("%s\n", s);   // C LAB 2026
    return 0;
}

toupper changes lowercase letters and leaves everything else as it is.

See it in memory

In our free interactive lab you can watch printf hunt for the '\0' one character at a time, see the garbage that appears without a terminator, and compare scanf and fgets reading the same name — including what is left behind in the input buffer:

Quick summary

  • A C string is a char array that ends with '\0'.
  • The array needs one more cell than the number of characters.
  • printf("%s"), strlen and all string functions stop at the first '\0'.
  • scanf("%s") reads one word; fgets reads a whole line (and keeps the '\n').
  • Copy with strcpy, compare with strcmp — never with = or ==.

Practice

  1. Write a loop that counts the vowels in a string.
  2. Reverse a string in place by swapping characters from both ends.
  3. Read a full name with fgets, remove the newline, and print it in capital letters.
  4. Check whether a word is a palindrome (level, madam).

Once you think of strings as "characters followed by a zero", they stop being mysterious.