Strings and Characters

C-Style Strings and Null Terminators

A C style string is really just a regular character array terminated with a special character called the null terminator.

This terminator is zero valued and can be represented as '\0'.

Anything that treats an array as a string will keep reading until it hits this terminator.

It's important that the character array being used as a C style string has space for both the visible characters and for the null terminator, '\0'.

For instance, the visible characters "Hello" will occupy five positions of the character array. The character array needs to have space for six positions, because the sixth position must be reserved for the null terminator.

#include <iostream>

int main()
{
    char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

    std::cout << greeting << '\n';

    return 0;
}

When std::cout reads the character array, it will start at index 0 and continue reading until it sees the null terminator, at which point it will stop printing, but not before.

If the terminator is forgotten, the character array is not properly null terminated, and when you send it to std::cout, it may continue writing beyond the boundaries of the array, with results that are (in the most technical of terms) undefined.

A more convenient way to create a C style string than actually using \0 is to initialize an array of characters using string literals.

#include <iostream>

int main()
{
    char greeting[] = "Hello";

    std::cout << greeting << '\n';

    return 0;
}

A character array initialized this way actually has a "hidden" null terminator. So, a string literal of "Hello" is actually stored in six positions within the character array, including the terminator (even though the terminator isn't usually visible or printed in code, except when treated as an integer or character literal itself).

The compiler will create a character array capable of storing those five characters plus the null terminator (thus making the array six characters long).

If we need to modify a C style string, a character can simply be replaced using array indexing in square brackets. Modifying one of the visible characters in the string won't change the terminator, unless we overwrite it.

#include <iostream>

int main()
{
    char word[] = "stack";
    word[0] = 'S';

    std::cout << word << '\n';

    return 0;
}

However, so long as there is a null terminator character following the last logical character in the string, we are free to change any characters before the terminator that we want.

A C style string has no way of storing how many characters are inside it. Any function that has to manipulate a C style string has to start at the first character and move through the array until it finds the null terminator '\0'.

Therefore, it is crucial that the terminator character stays in the correct place and is actually the terminator! Otherwise, if you lose the terminator or accidentally move it further into the array, functions reading the string will continue into and read whatever comes after the misplaced terminator.

What we often forget to do when using C style strings is to reserve space for the terminator. An array that has to store 5 character letters would normally require 5 positions; however, we must remember to include one additional space position for the null terminator.

Therefore, instead of 5 positions, an array that stores the characters 'H', 'e', 'l', 'l', 'o' will need 6 positions in order to store the string "Hello\0".

Failing to do this will cause the character array to not properly "hold" the C style string, and any function trying to read the array will do so up until it hits a zero and will be treating whatever comes beyond the array as belonging to it as well, which would be considered undefined.

Exercise: C-Style Strings and Null TerminatorsStarter code, hints and solutionOpenClose
Guided practiceBeginner · 10–15 min

Practice: C-Style Strings and Null Terminators

Work through the mission, reveal hints only when needed, and compare your result with the model solution.

Your challenge

Change the C-style string initializer to frame and replace its first character with F. Preserve the null terminator and predict the output.

Mission checklist

  1. Run the starter as a baseline, then predict the change requested in Your challenge.
  2. Make that change in your editor; use the lesson-specific hints if you need help.
  3. Compile and run your answer, then compare with the worked solution and explain the result.

Starter program

This is the working baseline, not the completed answer. Compile as C++20, then make the change described above.

#include <iostream>

int main()
{
    char word[] = "stack";
    word[0] = 'S';

    std::cout << word << '\n';

    return 0;
}

Hints

Hint 1

word contains the five letters of "stack" plus an automatic null terminator. Replacing word[0] changes a letter without changing the array length.

Hint 2

Use another short word in the initializer and change a valid character index. Leave its terminating \0 intact so std::cout knows where the C-style string ends.

Worked solution

The initializer is now frame and the first character is replaced with F. The array keeps its automatic null terminator, so std::cout prints Frame without reading past the string.

#include <iostream>

int main()
{
    char word[] = "frame";
    word[0] = 'F';

    std::cout << word << '\n';

    return 0;
}

Example output

Frame

0 comments

No comments yet. Be the first.

Add a comment

About CppLearn

CppLearn is an interactive, free reference for modern C++. In each lesson, you'll find out how the language works, rather than just lines of code that you can copy and paste. We cover concepts starting from beginner lessons on fundamentals and proceed to templates, move semantics, smart pointers, and areas that usually trap or scare C++ learners.