Является ли NULL в C обязательным / определено равным нулю? - PullRequest
49 голосов
/ 27 ноября 2011

NULL, по-видимому, равно нулю в моих тестовых программах GCC, но википедия говорит, что NULL требуется только для указания на неадресуемую память.

Какие-нибудь компиляторы делают NULL ненулевым?Мне любопытно, является ли if (ptr == NULL) лучшей практикой, чем if (!ptr).

Ответы [ 4 ]

63 голосов
/ 27 ноября 2011

NULL гарантированно равно нулю, возможно, приведено к (void *) 1 .

C99, §6.3.2.3, ¶3

Целочисленное константное выражение со значением 0, или такое выражение, приведенное к типу void *, называется константой нулевого указателя. (55) Если константа нулевого указателя преобразуется в тип указателя, результирующий указатель, называемыйнулевой указатель, гарантированно сравнивает неравный указатель с любым объектом или функцией.

И примечание 55 гласит:

55) Макрос NULL определен в <stddef.h> (и другие заголовки) в качестве константы нулевого указателя.

Обратите внимание, что из-за того, как сформулированы правила для нулевых указателей, значение, которое вы используете для назначения / сравнения нулевых указателей, гарантированно равно нулю., но битовая комбинация, фактически сохраненная в указателе, может быть любой другой вещью (но AFAIK только несколько очень эзотерических платформ воспользовались этим фактом, и это не должно быть проблемой в любом случае, поскольку, чтобы «увидеть» базовую битовую комбинацию, вы должны перейти к UB - в любом случае).

Таким образом, что касается стандарта, две формы эквивалентны (!ptr эквивалентно ptr==0 в соответствии с §6.5.3.3 ¶5, а ptr==0 эквивалентно ptr==NULL);if(!ptr) также довольно идиоматичен.

При этом я обычно пишу явно if(ptr==NULL) вместо if(!ptr), чтобы было совершенно ясно, что я проверяю нулевой указатель вместо некоторого логического значения.

  1. Обратите внимание, что в C ++ преобразование void * не может присутствовать из-за более строгих правил неявного приведения, которые делают использование таких NULL громоздкими (вам придется явно преобразовывать его в тип сравниваемого указателя каждыйвремя).
11 голосов
/ 28 ноября 2011

Из языкового стандарта:

6.3.2.3 Указатели
...
3 Целочисленное константное выражение со значением 0 или такое выражение, приведенное к типу void *, называется константой нулевого указателя . 55) Если константа нулевого указателя преобразуется в тип указателя, результирующий указатель, называемый нулевой указатель , гарантированно сравнивает неравные на указатель на любой объект или функцию.
...
55) Макрос NULL определен в <stddef.h> (и других заголовках) как константа нулевого указателя; см. 7.17.

Учитывая этот язык, макрос NULL должен вычисляться как выражение с нулевым значением (либо недокументальный литерал 0, выражение типа (void *) 0, либо другой макрос или выражение, которое в конечном итоге оценивается как 0 ). Выражения ptr == NULL и !ptr должны быть эквивалентны. Вторая форма имеет тенденцию быть более идиоматическим C-кодом.

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

3 голосов
/ 28 ноября 2011

На практике то же самое, но NULL отличается от нуля. Поскольку ноль означает, что есть значение, а NULL означает, что его нет. Таким образом, теоретически они различны, значение NULL имеет другое значение, и в некоторых случаях это различие должно быть полезным.

2 голосов
/ 27 ноября 2011

на практике нет,! Ptr правильный

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...