11

currently I am reading "A tour of C++" by Byarne Stroustrup. The thing that matters: on "pointers, arrays and references" he gave an example about using nullptr like this:

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;
}

In my my main:

int main(){

    char* str = "Good morning!";
    char c = 'o';
    std::cout << count_x(str, c) << std::endl;

    return 0;
}

When I run the program it crashes I get an exception thrown at line

if (*p == x)

If I change the loop to be like this:

for (; *p; p++)
    if (*p == x)
        ++count;

Now everything works fine! I am using MSVC++ 14.0.

  • The same code I ran on ideone I don't get an exception but the result is always 0 which should be 3:

https://ideone.com/X9BeVx

WonFeiHong
  • 445
  • 4
  • 16
  • 1
    @DeiDei: Yes I just copied and pasted the code. What I add is main code. – WonFeiHong Dec 16 '17 at 12:05
  • 1
    @DeiDei: How should this be correct: `*p != nullptr`? as I guess `nullptr` is only for addresses pointers point to not a the value they sore in address they point to. – WonFeiHong Dec 16 '17 at 12:07
  • 5
    I didn't find this in any of the errata's for "A tour of C++". You should write to Bjarne and let him know. This is a mistake. – StoryTeller - Unslander Monica Dec 16 '17 at 12:07
  • 3
    The code from this [online version](https://isocpp.org/images/uploads/2-Tour-Basics.pdf#page=11) uses a correct check - where did you copy your code from? – hnefatl Dec 16 '17 at 12:12
  • 1
    @hnefatl: Yes that is correct. But I don't know why my book is incorrect? It is in extension "epub". Thank you. – WonFeiHong Dec 16 '17 at 12:22
  • 4
    BTW, `char* str = "Good morning!";` is not a valid C++ code. `str` should be of type `const char*`. MSVC++ is too permissive. – Ruslan Dec 16 '17 at 15:31

2 Answers2

15

p != nullptr and *p perform very different checks.

The former checks that the pointer itself contains a non-null address. While the latter checks that the address being pointed at contains something that is not 0. One is clearly appropriate in the loop, where the buffer's content is checked, while the other is not.

You segfault because you never stop reading the buffer (a valid pointer is unlikely to produce null when it is incremented). So you end up accessing way beyond your buffer limit.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
1

Remember that you are using C language feature.

Your problem is in your for loop. After the pointer reaches the last element of your character array it points to the end of the array not the nullptr.

Imagine you have a character array such as const char *a ="world" and ptr points to the

     +-----+     +---+---+---+---+---+---+
ptr :| *======>  | w | o | r | l | d |\0 |
     +-----+     +---+---+---+---+---+---+  

the last element which ptr points to is '\0' and in your for you should change your code as below:


for (; *p != 0; p++) {
        if (*p == x)
            ++count;
    }

output : 3

Pouyan
  • 363
  • 5
  • 22