A C string is a character array that ends with a null terminator.
All characters have a symbol table value. The null terminator is the symbol value 0
(zero). It is used to mark the end of a string. This is necessary since the size of the string isn't stored anywhere.
Therefore, every time you allocate room for a string, you must include sufficient space for the null terminator character. Your example does not do this, it only allocates room for the 5 characters of "hello"
. Correct code should be:
char str[6] = "hello";
Or equivalently, you can write self-documenting code for 5 characters plus 1 null terminator:
char str[5+1] = "hello";
But you can also use this and let the compiler do the counting and pick the size:
char str[] = "hello"; // Will allocate 6 bytes automatically
When allocating memory for a string dynamically in run-time, you also need to allocate room for the null terminator:
char input[n] = ... ;
...
char* str = malloc(strlen(input) + 1);
If you don't append a null terminator at the end of a string, then library functions expecting a string won't work properly and you will get "undefined behavior" bugs such as garbage output or program crashes.
The most common way to write a null terminator character in C is by using a so-called "octal escape sequence", looking like this: '\0'
. This is 100% equivalent to writing 0
, but the \
serves as self-documenting code to state that the zero is explicitly meant to be a null terminator. Code such as if(str[i] == '\0')
will check if the specific character is the null terminator.
Please note that the term null terminator has nothing to do with null pointers or the NULL
macro! This can be confusing - very similar names but very different meanings. This is why the null terminator is sometimes referred to as NUL
with one L, not to be confused with NULL
or null pointers. See answers to this SO question for further details.
The "hello"
in your code is called a string literal. This is to be regarded as a read-only string. The ""
syntax means that the compiler will append a null terminator in the end of the string literal automatically. So if you print out sizeof("hello")
you will get 6, not 5, because you get the size of the array including a null terminator.
It compiles cleanly with gcc
Indeed, not even a warning. This is because of a subtle detail/flaw in the C language that allows character arrays to be initialized with a string literal that contains exactly as many characters as there is room in the array and then silently discard the null terminator (C17 6.7.9/15). The language is purposely behaving like this for historical reasons, see Inconsistent gcc diagnostic for string initialization for details. Also note that C++ is different here and does not allow this trick/flaw to be used.
char *str = "hello";
...str[0] = foo;
problem. – Hendrix