Для наиболее педантичного ответа вот соответствующие разделы спецификации.
Во-первых, вот как работают if
операторы из раздела 6.4.4:
Значением условия, которое является инициализированным объявлением в выражении, отличном от оператора switch, является значение объявленной переменной , неявно преобразованной в тип bool
. Если это преобразование неверно, программа некорректно сформирована.
"Но как указатели конвертируются в bool
с?" Вы можете спросить. Ну, вот & 4.12.1:: -)
Значение арифметики, перечисления, указатель или указатель на тип члена может быть преобразовано в значение типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется в false; любое другое значение преобразуется в true.
Итак, это означает, что утверждение
if (ptr)
эквивалентно
if ((bool) ptr)
что в свою очередь эквивалентно
if (ptr == NULL)
А как же
if (!ptr)
Ну, спецификация C ++, раздел 5.3.1.8, говорит, что
Операнд оператора логического отрицания! неявно преобразуется в bool
(пункт 4); его значение равно true
, если преобразованный операнд равен false
и false
в противном случае. Тип результата: bool
.
Так что это означает, что
if (!ptr)
эквивалентно
if (!(bool)ptr)
, что в свою очередь эквивалентно
if (!(ptr == NULL))
что в конечном итоге эквивалентно
if (ptr != NULL)
Уф! Это был интересный поиск. Надеюсь, что это отвечает на ваш вопрос!
Конечно, в этой истории есть кое-что еще. NULL
не является частью языка C ++; это макрос в <cstddef>
, определенный как
#define NULL 0
Это работает, потому что стандарт C ++ определяет нулевой указатель в & sect; 4.10.1 как
Константа нулевого указателя - это целочисленное константное выражение (5.19) rvalue типа integer, которое оценивается как ноль . Константа нулевого указателя может быть преобразована в тип указателя; результат является нулевым значением указателя этого типа и отличается от любого другого значения указателя на объект или указателя на тип функции
Итак, чтобы быть более правильным, я должен был использовать числовой литерал 0 в приведенных выше примерах. Однако, если у вас есть <cstddef>
, то после предварительной обработки это работает с тем же кодом.