Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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), чтобы сделать это ясным, что я проверяю указатель на nullity вместо некоторого логического значения.


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

Ответ 2

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

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

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

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

Ответ 3

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

Ответ 4

на практике нет,! ptr правильно