Примечание. Этот ответ относится к языку C, а не к C ++.
Нулевые указатели
Целочисленный константный литерал 0
имеет разные значения в зависимости от контекста, в котором он используется. Во всех случаях это все еще целочисленная константа со значением0
, это просто описано по-разному.
Если указатель сравнивается с константным литералом 0
, то это проверка, чтобы увидеть, является ли указатель нулевым указателем. Это 0
затем называется постоянной нулевой указатель. Стандарт C определяет, что 0
приведение к типуvoid *
является как нулевым указателем, так и константой нулевого указателя.
Кроме того, для удобства чтения макрос NULL
предоставляется в заголовочном файле stddef.h
. В зависимости от вашего компилятора может быть возможно#undef NULL
и переопределить его в нечто дурацкое.
Поэтому вот несколько допустимых способов проверить наличие нулевого указателя:
if (pointer == NULL)
NULL
определяется для сравнения равным нулевому указателю. Это реализация, определяемая тем, что является фактическим определением NULL
, при условии, что это допустимая константа нулевого указателя.
if (pointer == 0)
0
это еще одно представление константы нулевого указателя.
if (!pointer)
Это if
утверждение неявно проверяет «не 0», поэтому мы обращаемся к значению «0».
Ниже приведены недействительные способы проверки нулевого указателя:
int mynull = 0;
<some code>
if (pointer == mynull)
Для компилятора это не проверка на нулевой указатель, а проверка на равенство двух переменных. Это может сработать, если mynull никогда не изменится в коде, а константа оптимизации компилятора сложит 0 в оператор if, но это не гарантируется, и компилятор должен выдать хотя бы одно диагностическое сообщение (предупреждение или ошибка) в соответствии со стандартом C.
Обратите внимание, что это пустой указатель на языке Си. Это не имеет значения в базовой архитектуре. Если в базовой архитектуре значение нулевого указателя определено как адрес 0xDEADBEEF, то компилятор должен разобраться в этом беспорядке.
Таким образом, даже в этой забавной архитектуре следующие способы все еще являются допустимыми способами проверки на нулевой указатель:
if (!pointer)
if (pointer == NULL)
if (pointer == 0)
Ниже приведены недействительные способы проверки нулевого указателя:
#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)
так как они рассматриваются компилятором как обычные сравнения.
Нулевые символы
'\0'
определяется как нулевой символ - это символ со всеми битами, установленными в ноль. Это не имеет ничего общего с указателями. Однако вы можете увидеть что-то похожее на этот код:
if (!*string_pointer)
проверяет, указывает ли указатель строки на нулевой символ
if (*string_pointer)
проверяет, указывает ли строковый указатель на ненулевой символ
Не путайте их с нулевыми указателями. Просто потому, что битовое представление одно и то же, и это допускает некоторые удобные перекрестные случаи, на самом деле это не одно и то же.
Кроме того, '\0'
является (как и все символьные литералы) целочисленной константой, в данном случае со значением ноль. Таким образом, '\0'
он полностью эквивалентен 0
целочисленной константе без приукрашивания - единственное отличие заключается в том, что намерение, которое оно передает читателю-человеку («Я использую это как нулевой символ»).
Ссылки
См Вопрос 5.3 comp.lang.c FAQ для более. Смотрите этот PDF для стандарта C. Ознакомьтесь с разделами 6.3.2.3. Указатели, пункт 3.