Previous Table of Contents Next


7.2.7. String Literals

Now that we understand characters, pointers, and arrays, we can discuss strings. The reason that so many preliminaries are needed to understand strings is that

  C++ does not have a built-in string type. Instead, strings are implemented as part of the library.
  However, it is obviously essential to be able to write string literals as part of a program.

This puts the language in an interesting dilemma: It doesn’t make sense for built-in constructions such as string literals to know about specific library types, but if literals have a built-in type, then they won’t have the same type as string variables.

C++ resolves this dilemma by choosing the second alternative: After executing

   string s = “Hello, world!”;

the variable s actually has a different type from the literal “Hello, world!”. Fortunately, this discrepancy does not cause much trouble in practice—but it is important to know about it.

A string literal is actually an array of const characters, which is initialized before the program executes. To make it possible to determine the length of the array, the compiler quietly inserts an extra, null character at the end of the string. As with any other array, a string literal is usually converted automatically into a pointer to the initial character of the array.

In other words, for example, the type of “Hello, world!” is “pointer to const character,” and it evaluates to a pointer to an array of 14 characters. Indeed, when we write

   cout << “Hello, world!” << endl;

we could have achieved the same effect, albeit more clumsily, by saying

   const char Hello[14] = {
        ‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘,’, ‘ ‘,
        ‘w’, ‘o’, ‘r’, ‘l’, ‘d’, ‘!’, ‘\0’
   };

   cout << Hello << endl;

In either case, the << operator is presented with a pointer to the initial H of the string, and the library figures out how many characters to print by copying characters to the standard output one at a time until it is about to copy a ‘\0’ character.

In contrast, if we were to say

   string hello = “Hello, world!” << endl;

   cout << hello << endl;

the library would be presented with an object of type string, whose properties we have yet to discuss, and would produce exactly the same output through completely different means.

As another illustration of how to use arrays, pointers, and numbers, here is one way to implement a standard C++ library function called strlen. This function takes a pointer to the initial element of a null-terminated array of characters and returns the number of characters in the array, excluding the null at the end:

   int strlen(const char* p)
   {
        int result = 0;

        while (*p != ‘\0’) {
              ++p;
              ++result;
        }
        return result;
   }

Note that although p points at immutable memory, that is no bar to changing the value of p itself.

Here is a somewhat terser way to achieve the same effect:

   int strlen(const char* p)
   {
        const char* q = p;

        while (*q++ != ‘\0’) { }

        return q - p - 1;
   }

To convince yourself that this function works, note that *q++ has the same value as *q but has the side effect of incrementing q. That means that when the loop exits, q will point one character beyond the ‘\0’ terminator. Note also that this version depends on the ability to point one element beyond the end of any array.


Previous Table of Contents Next