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

6
  • 1
    @DeiDei: Yes I just copied and pasted the code. What I add is main code. Commented Dec 16, 2017 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. Commented Dec 16, 2017 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. Commented Dec 16, 2017 at 12:07
  • 3
    The code from this online version uses a correct check - where did you copy your code from? Commented Dec 16, 2017 at 12:12
  • 4
    BTW, char* str = "Good morning!"; is not a valid C++ code. str should be of type const char*. MSVC++ is too permissive. Commented Dec 16, 2017 at 15:31

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

But this is considered incorrect: *p = nullptr isn't it?
@WonFeiHong - Yes, that would be incorrect. *p doesn't have a pointer type, so it won't be possible to compare it with nullptr. You'll get a compiler error when you try
Yeah if you want to make the comparison more explicit you can do *p != '\0' though just *p works fine too...
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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.