4

I am confused by the use of nullptr in an example from A Tour of C++:  

int count_x(char* p, char x)
// count the number of occurrences of x in p[]
// p is assumed to point to a zero-terminated array of char (or to nothing)
{
    if (p==nullptr) return 0; 
    int count = 0;
    for (; p!=nullptr; ++p)
        if (*p==x) ++count;
    return count; 
}
// The definition of count_x() assumes that the char* is a C-style string,
// that is, that the pointer points to a zero-terminated array of char.

I understand that count_x should terminate if p is unassigned, and the for loop should terminate when it reaches the end of the C-style string referenced by p.

However, when I build a main function to use count_x(), it never seems to terminate correctly:

int main () {

    char teststring[] = {'b', 'l', 'a', 'h', '\0'}; 
    cout << "teststring is: " << teststring << endl; 
    cout << "Number of b's is: " << count_x(teststring, 'b') << endl; 

    return 0;  
}

Executing this prints a lot of garbage, and then exits with a segmentation fault. If I replace the for (; p!=nullptr; ++p) in count_x with for (; *p!='\0'; ++p), it executes properly. I guess this means that the string is not terminated correctly. If so, how do I terminate a C-style string so that nullptr can be used here?

Edit: there's been a discussion in the comments that's clarified this situation. I'm using the first print of the book from September 2013, where the above is printed in error. The third print of the book from January 2015 (linked in the comments) has the corrected example which uses for (; *p!=0; ++p) instead of for (; p!=nullptr; ++p). This correction is also documented in the errata for the book. Thanks!

Edit2: Sorry guys, this was apparently already asked on SO earlier here: Buggy code in "A Tour of C++" or non-compliant compiler?

Community
  • 1
  • 1
  • 3
    The `count_x` function you posted is broken. `nullptr` does not work that way. – user2357112 Jun 17 '16 at 22:51
  • 12
    That code is just broken. Ignore it. They probably meant `for (; *p != 0; ++p)`. – David Schwartz Jun 17 '16 at 22:52
  • Looks like a mistake in the book to me. – Galik Jun 17 '16 at 22:53
  • What edition are you reading? I don't see this in either the [first edition](http://www.stroustrup.com/Tour_printing2.html) or [second edition](http://www.stroustrup.com/Tour_printing3.html) errata. – user2357112 Jun 17 '16 at 22:54
  • 1
    The book [seems to use a while loop](https://books.google.com/books?id=-VNsAQAAQBAJ&pg=PA12&lpg=PA12&dq=a+tour+of+C%2B%2B+count_x&source=bl&ots=Dw2BrizUdW&sig=gIJ2QkyNJ1vNtS6XzYbxSryzHWw&hl=en&sa=X&ved=0ahUKEwj6jsXAk7DNAhVV_mMKHXTHArkQ6AEIMzAD#v=onepage&q=a%20tour%20of%20C%2B%2B%20count_x&f=false). What edition are you using? – geometrian Jun 17 '16 at 22:55
  • @imallett The example I'm using is right above the `while` loop version. – Continuous Tone Jun 17 '16 at 22:56
  • 1
    @imallett: One page up, there's also a version with a `for` loop, but that version is using the correct test instead of a comparison with `nullptr`. – user2357112 Jun 17 '16 at 22:56
  • Minor note: "I understand that count_x should terminate if `p` is unassigned" not exactly. It should "return 0 if `p` has been assigned to null". It would be undefined behavior to pass in an unassigned `p`. – geometrian Jun 17 '16 at 22:56
  • *That* appears in a C++ book by B. Stroustrup? Get outta here. :) – Kaz Jun 17 '16 at 22:57
  • @imallett @user2357112 Yes, I seem to be using an old version of the book. The version with `*p != 0` works fine! – Continuous Tone Jun 17 '16 at 22:57
  • 3
    There might be an error in the errata, or the first edition might have used a different function name. Aside from the name, this seems to match the first edition errata for chapter 1: "pp 11-12: The code for count_if() is wrong (doesn't do what it claims to)..." The page numbers seem to match. – user2357112 Jun 17 '16 at 23:03
  • 1
    i suspect somebody went through the examples replacing NULL by nullptr and the old code had NULL. That old code would have worked (at least for some definitions of NULL) – pm100 Jun 17 '16 at 23:46

1 Answers1

12

No, a NULL pointer is not used to terminate strings. The NUL character is used. They are different things, but if you assign either of them to an integer in C, the result is always the same: zero (0).

A NUL character is represented in C as '\0' and takes up one char of storage. A NULL pointer is represented in C as 0, and takes up the same storage as void *. For example, on a 64-bit machine, a void * is 8 bytes while '\0' is one byte.

I.e., nullptr is not the same thing as '\0'. And the character is the null character, called NUL, but it is not supposed to be called a NULL byte or a NULL character.

Heath Hunnicutt
  • 18,667
  • 3
  • 39
  • 62