NULL всегда ложно? - PullRequest
       11

NULL всегда ложно?

49 голосов
/ 20 января 2009

Можно ли предположить, что NULL всегда переводится в false в C?

void *somePtr = NULL;

if (!somePtr) {
  /* This will always be executed? */
}

Или должна быть проведена явная проверка значения NULL?

Ответы [ 9 ]

49 голосов
/ 20 января 2009

Да. NULL оценивается как ложное, поскольку C считает любое ненулевое значение истинным, а любое нулевое значение ложным. NULL - это адрес zero, который рассматривается как таковой в сравнениях, и я полагаю, что он будет повышен до int для логической проверки. Я ожидаю, что ваш код будет доступен для чтения любому, кто знаком с C, хотя я, вероятно, сделаю проверку явной.

В программировании на C и C ++ два null указатели гарантированно сравниваются равны; ANSI C гарантирует, что любой ноль указатель будет равен 0 в сравнение с целочисленным типом; кроме того, макрос NULL определен в качестве константы нулевого указателя, то есть значение 0 (либо в виде целочисленного типа, либо преобразован в указатель на void), поэтому нулевой указатель будет сравниваться равным NULL.

Ссылка: http://en.wikipedia.org/wiki/Null_pointer#Null_pointer

16 голосов
/ 20 января 2009

Язык 'C' датируется эпохой, когда (void *) 0 действительно мог быть действительным указателем. Не так давно микропроцессоры 8080 и Z80 имели вектор прерывания по адресу 0. Столкнувшись с таким выбором архитектуры, он ничего не мог сделать, кроме как позволить файлу заголовка объявить значение NULL. Существовали некоторые компиляторы, теперь давно забытые, где NULL не был равен (void *) 0 (0xffff был следующей альтернативой), что давало вашему оператору if () неопределенное поведение.

C ++ милостиво покончил с этим, нулевой указатель назначается и проверяется на 0.

16 голосов
/ 20 января 2009

Никогда нельзя предполагать что-либо.

Явная проверка также более понятна в отношении того, что вы тестируете.

11 голосов
/ 20 января 2009

Да (по крайней мере, для любого компилятора C, соответствующего стандартам!)

Из comp.lang.c FAQ :

В: Допустимо ли сокращенное сравнение указателей `` if (p) '' для проверки ненулевых указателей? Что если внутреннее представление для нулевых указателей отлично от нуля?

A: Это всегда верно.

5 голосов
/ 20 января 2009

NULL - это просто определение препроцессора. Это в stdio.h. Как правило, только безумный человек может переопределить его, но это возможно. Пример:

#include <stdio.h>
#ifdef NULL
#undef NULL
#define NULL 1
#endif

void main()
{

        if (NULL)
                printf("NULL is true\n");
        else
                printf("NULL is false\n");
}

В этом коде будет напечатано «NULL is true». Попробуй, если не веришь мне. Ваш компилятор может даже не предупредить вас, что вы делаете что-то странное.

2 голосов
/ 20 января 2009

Я просто отсылаю вас к Вопросу 5.3 C-FAQ. Это отвечает на этот точный вопрос.

2 голосов
/ 20 января 2009

NULL определяется как постоянный указатель, который гарантированно указывает на бесполезное / несуществующее место в памяти. Большинство реализаций NULL являются ((void *)0), но это не обязательно, что это так.

0 голосов
/ 20 января 2009

Да, в основном.

Прежде всего, NULL - это typedef. Я мог бы по-королевски напортачить, сказав в ранее включенном заголовке

#define NULL 1

Это может не иметь большого смысла, но с каких это пор код других людей когда-либо имел смысл? :)

Кроме того, хотя это, вероятно, синтаксически безопасно, оно не является семантически правильным. NULL означает «ничего», ни true, ни false, ни логическое значение, ни int, ни string. Это означает «символ для ничего». Так что тестирование на NULL больше похоже на философскую проблему: если дерево падает в лесу и if(listener), издает ли он звук?

Сделайте всем одолжение и будьте внимательны при тестировании против NULL.

0 голосов
/ 20 января 2009

* NULL всегда нацелен на 0x00L. Вы можете считать это ложным, но для уверенности всегда делайте явную проверку.

...