Является ли NULL указателем?

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

Я уже пробовал искать в Интернете, но не смог найти ответа, поэтому мое последнее средство здесь


person Joe    schedule 04.04.2019    source источник
comment
Итак, что вы думаете, присваивая NULL указателю? Что он содержит?   -  person phuclv    schedule 04.04.2019
comment
Это зависит от того, что вы подразумеваете под указателем. Поскольку вы пометили это концептуально, я думаю, вы можете использовать термин «указатель» в смысле, отличном от определения формального языка.   -  person Raymond Chen    schedule 04.04.2019
comment
@phuclv указатель указывает ни на что или на ноль   -  person Joe    schedule 04.04.2019
comment
указатель, который ни на что не указывает, является нулевым указателем   -  person phuclv    schedule 05.04.2019
comment
@Joe: вы можете принять один из ответов, нажав на серую галочку под его оценкой.   -  person chqrlie    schedule 13.04.2019
comment
Это целочисленная константа в C++ и 0, преобразованная в (void *) в POSIX.   -  person S.S. Anne    schedule 04.08.2019


Ответы (3)


В C NULL — это макрос, который расширяется до константы нулевого указателя.

7.19p3

Макросы

NULL, который расширяется до определяемой реализацией константы нулевого указателя; ...

Константа нулевого указателя представляет собой целочисленное константное выражение со значением 0 (например, 0, 1-1, 42*0LL и т. д.) или такое выражение, приведенное к (void*).

6.3.2.3p3

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

Наиболее распространенные реализации C определяют NULL как 0, 0L или ((void*)0).

Итак, вы правы. NULL не обязательно должен быть указателем.

(IIRC, С++ даже не допускает приведения (void*) к NULL, что означает, что NULL в С++ всегда имеет целочисленный тип. Из-за этого и из-за того, что указатели void* не так легко сравниваются с обычными указателями в С++, C++>=11 теперь имеет специальный nullptr ключевое слово.)

person PSkocik    schedule 04.04.2019
comment
@Joe Если в нем есть приведение (void *), то он имеет тип указателя (void). - person PSkocik; 04.04.2019
comment
@Joe NULL — это макрос, расширяющийся до неопределенного значения, которое можно сравнить с указателями на равенство. Значение NULL может иметь тип void-указателя или может быть целым числом. Обычно это 0, 0L или ((void*)0). - person PSkocik; 04.04.2019
comment
@PSkocik Обратите внимание, что этот вопрос был помечен как концептуальный, а не языковой, поэтому я предполагаю, что вопрос не столько в NULL макросе, сколько в нулевом указателе как концепции. - person Raymond Chen; 08.04.2019

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

Между char *p = 0; и char *p = NULL; нет семантической разницы, но последний более явный, и использование NULL вместо 0 более информативно в обстоятельствах, когда другой операнд явно не является указателем или если сравнение с целым числом выглядит как несоответствие типов:

FILE *fp = fopen("myfile", "r");
if (fp == NULL) {
    /* report the error */
}

Точно так же в C нет семантической разницы между '\0' и 0, они оба являются константами int. Первый — нулевой байт, второй — нулевое значение. Разумное использование 0, '\0' и NULL может показаться бесполезным, но делает код более читабельным для других программистов и для вас самих.

Путаница может возникнуть из-за неправильного написания или неверного понимания нулевого указателя как указателя NULL. Стандарт C был тщательно прочитан для использования только нулевого указателя и обращения к NULL только как к макросу NULL.

Однако обратите внимание, что одно из принятых определений NULL, #define NULL ((void*)0) делает NULL нулевым указателем на void.

person chqrlie    schedule 07.04.2019

Нет ничего плохого в идее «указателя на адрес 0».

Правило состоит в том, что вам запрещено разыгрывать его ... ему разрешено существовать, и если он будет создан, он будет соответствовать любым критериям «указателя», о которых я могу думать. Просто потому, что это не указатель на что-то...

person l.k    schedule 07.04.2019