Ch5.8: C‑style Strings

Overview

A C‑style string is a C‑style array of characters terminated by the special character '\0' (the null terminator). This convention originates from the C language and remains part of modern C++ for compatibility.

In this chapter, you will learn:

1. What is a C‑style string?

A C‑style string is simply a C‑style array of char that ends with '\0'.


char s[6]{'H', 'e', 'l', 'l', 'o', '\0'};

Memory layout:


Address:   2000  2001  2002  2003  2004  2005
Memory:    [ H ][ e ][ l ][ l ][ o ][ \0 ]

2. Why C‑style strings must end with '\0'

C‑style strings do not store their length. Instead, code that processes them scans characters until it finds '\0'.

If the null terminator is missing:


char bad[5]{'H', 'e', 'l', 'l', 'o'};  // ❌ no '\0'

3. String literals

A string literal such as "Hello" is stored as a constant C‑style array of char with a null terminator.


char const *p = "Hello";

Memory layout:


"Hello" → [ H ][ e ][ l ][ l ][ o ][ \0 ]

Important rules:


// char *p = "Hello";   // allowed to compile, but dangerous
// p[0] = 'h';          // ❌ undefined behavior

Always write char const* for pointers to C‑style strings.

4. C‑style strings are C‑style arrays

A C‑style string is just a C‑style array of char. Therefore, all rules from previous chapters apply:


char s[6]{"Hello"};

char const *p = s;   // decay
char const *q = p + 1; // points to 'e'

5. Why fast_io prints string literals but not pointers to them

A string literal is fundamentally a C‑style array. fast_io recognizes C‑style arrays of characters and prints them as strings.


print("hello world\n");   // ✔ works

However, once the array decays to a pointer, fast_io cannot know whether the pointer refers to a valid C‑style string. It refuses to print raw pointers directly.


char const *ptr = "hello world\n";

// print(ptr);   // ❌ does NOT work

fast_io must assume:

This is why:


print("hello");     ✔ works (array)
print(ptr);         ❌ does not work (pointer)

To print a pointer as a C‑style string, use:


println(os_c_str(ptr));

6. strlen and strnlen

strlen computes the length of a C‑style string by scanning until '\0'.


char s[6]{"Hello"};

std::size_t n = strlen(s);   // returns 5

Important: strlen assumes the string is properly null‑terminated. If '\0' is missing, it will read past the end → undefined behavior.

strnlen

strnlen is similar but stops after a maximum number of characters.


std::size_t n = strnlen(s, 6);   // safe upper bound

strnlen is safer because it prevents scanning unbounded memory.

7. fast_io manipulators for C‑style strings

fast_io provides manipulators for printing pointers and C‑style strings.

pointervw(ptr)

Prints a pointer value as an address.


char const *p = "Hello";
println(pointervw(p));   // prints address of p

os_c_str(ptr)

Prints a null‑terminated C‑style string.


println(os_c_str(p));    // prints "Hello"

os_c_str(ptr, n)

Prints a C‑style string but stops after at most n characters.


println(os_c_str(p, 3));   // prints "Hel"

8. Wide and Unicode C‑style strings

C++ supports several character types, each with its own C‑style string form:

Each uses its own null terminator:


wchar_t  ws[]{L"Hello"};
char16_t u16s[]{u"Hello"};
char32_t u32s[]{U"Hello"};
char8_t  u8s[]{u8"Hello"};

All of them follow the same rules:

Key takeaways