Как правильно использовать nullptr?

В настоящее время я читаю "Тур по С++" by Byarne Stroustrup. Что имеет значение: на "указателях, массивах и ссылках" он привел пример об использовании nullptr следующим образом:

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

В моем основном:

int main(){

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

    return 0;
}

Когда я запускаю программу, она выходит из строя. Я получаю исключение, созданное в строке

if (*p == x)

Если я изменил цикл таким образом:

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

Теперь все работает отлично! Я использую MSVС++ 14.0.

  • Тот же код, что и я, на ideone Я не получаю исключение, но результат всегда 0, который должен быть 3:

https://ideone.com/X9BeVx

Ответ 1

p != nullptr и *p выполняют очень разные проверки.

Первая проверяет, что сам указатель содержит непустой адрес. Хотя последний проверяет, что адрес, на который указывает, содержит то, что не равно 0. Очевидно, что в цикле явно указано содержимое буфера, а другое - нет.

Вы segfault, потому что вы никогда не прекращаете чтение буфера (допустимый указатель вряд ли произведет null, когда он будет увеличен). Таким образом, вы получаете доступ за пределы вашего ограничения на буфер.

Ответ 2

Помните, что вы используете функцию языка C.

Ваша проблема в вашем цикле for. После того, как указатель достигнет последнего элемента массива символов , он указывает на конец массива, а не на nullptr.

Представьте, что у вас есть массив символов, такой как const char *a ="world" и ptr, указывает на

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

последний элемент, который ptr указывает на '\0', а в вашем for вы должны изменить свой код, как показано ниже:


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

вывод: 3