Как вы справляетесь с NUL?

Время от времени я сталкиваюсь с проблемой связи с другими программистами, когда мы говорим о NULL. Теперь NULL может быть

указатель NULL
символ NUL
пустой элемент данных в какой-то базе данных.


NUL кажется самым запутанным. Это символ ASCII 0x00.
Я обычно использую '\ 0' в своем коде для его представления. Некоторые разработчики в моей группе
предпочитают просто использовать 0, и пусть компилятор неявно передает его в char.


Что вы предпочитаете использовать для NUL? и почему?

Ответ 1

Я использую '\0' для nul-character и NULL для указателей, потому что в обоих случаях это яснее.

BTW, как 0, так и '\0' являются int в C, и каждый из них будет преобразован в char при сохранении в переменной char.

Ответ 2

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

Ответ 3

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

Ответ 4

  • Для работы со строками я всегда представляю нулевой символ как '\ 0'.
  • Для указателей я пытаюсь использовать implicit-conversion-to-boolean (if (! myPtr) или if (myPtr)) для недействительности указателя.
  • Если мне нужно значение по умолчанию для указателя, оно равно NULL, например. struct list_head = {0.0, NULL};).

END_OF_STRING глупо, поскольку это дополнительное косвенное отношение, которое просто путает новых читателей (каждый, кто не сразу распознает "\ 0", должен отходить от клавиатуры).

Еще одна вещь: я думаю, что разница между нулевым значением и пустым значением чрезвычайно важна при обсуждении моделирования данных. Это особенно актуально при обсуждении строк C-стиля или полей базы данных с возможностью NULL. Там огромная разница между тем, кто говорит вам: "У меня нет имени" и "Меня зовут".

Ответ 5

Если я правильно помню, большинство компиляторов C определяют NULL следующим образом:

#define NULL ((void*)0)

Это означает, что NULL интерпретируется как тип указателя (в C). Однако это может вызвать проблемы в гораздо более строгом мире С++. Например:

// Example taken from wikibooks.org
std::string * str = NULL; // Can't automatically cast void * to std::string *
void (C::*pmf) () = &C::func;
if (pmf == NULL) {} // Can't automatically cast from void * to pointer to member function.

Поэтому в текущих стандартных указателях С++ нулевые указатели должны быть инициализированы литералом 0. Очевидно, что люди так привыкли использовать определение NULL. Я думаю, что многие компиляторы С++ молча игнорируют проблему или переопределяют NULL как 0 в С++ код. Например:

#ifdef __cplusplus
#define NULL (0)
#else
#define NULL ((void*)0)
#endif

Стандарт С++ x0 теперь определяет ключевое слово nullptr для представления нулевых указателей. Visual С++ 2005 CLI/С++ компилятор также использует это ключевое слово при установке управляемых указателей на null. В текущих компиляторах вы можете создать шаблон для эмуляции этого нового ключевого слова.

Более подробная статья о wikibooks.org обсуждается с этой проблемой.

Ответ 6

@BKB:

Я вижу смысл в его совете, но "NULL" дает понять, что контекст является указателем. Это похоже на использование "0.0" для значений с плавающей запятой, как "\ 0" при работе с символами. (Аналогично, я предпочитаю видеть 0, если в арифметическом контексте используется char.)

Bjarne далее утверждает в этот FAQ, что NULL #defined как 0 в любом случае, поэтому стандартный код не должен иметь проблемы с ним. Я согласен с тем, что нотация all-caps является уродливой, но нам придется подождать до 0x (где nullptr будет доступно в качестве ключевого слова.)

Ответ 7

A one-L NUL, it ends a string. 
A two-L NULL points to no thing. 
And I will bet a golden bull 
That there is no three-L NULLL. 



(The name of the original author is, alas, lost to the sands of time.)

Ответ 8

NULL для баз данных, NIL для кода.

Ответ 9

Мне очень нравится

#define ASCII_NUL ('\0')

Я только изредка ошибаюсь '\ 0' как '0'. Но когда я это сделал, я обнаружил ошибку, которую очень трудно обнаружить при проверке кода, с вескими последствиями. Поэтому мне не нравится "\ 0" и предпочитает ASCII_NUL или 0 (конечно, последний имеет неправильный тип в С++). Очевидно, я использую '\ 0', где требуется согласованность с существующим кодом или руководствами по стилям.

Руководство по стилю Google С++, в котором содержится несколько вещей, которые мне нравятся, и некоторые из них я не знаю, но, кажется, в основном звучит, предпочитает NULL 0 для указателей. Он указывает, что NULL не может быть определен просто как 0 (или 0L), особенно в реализациях, где sizeof (void *) может не быть sizeof (int) (или sizeof (long int)).

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

Ответ 10

Хотя, в целом, я бы советовал использовать именованные константы, это одно исключение. Для меня, определяя:

#define NULL 0
#define END_OF_STRING '\0'

имеет такое же значение, как и определение:

#define SEVEN 7

который не является. И да, я знаю, что NULL уже определен компилятором, но я никогда не использую его. Для указателей 0; для символов, '\ 0'. Более длинный не всегда означает более выразительный.

Ответ 11

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

Для реализации это конкретный случай. Числа равны 0 (постфиксирован f для с плавающей запятой), указатели NULL, а символьные строки - 0.

Ответ 12

Системы, которые не используют двоичный код 0 для NULL, становятся все труднее найти. Они также имеют различные проблемы с переносимостью. Зачем? Поскольку в этих системах ни memset, ни calloc не могут очистить структуру, содержащую указатели правильно.

Ответ 13

const char END_OF_STRING = '\0';

Итак, когда вы говорите:

str[i] = END_OF_STRING;

или

if (*ptr == END_OF_STRING)

нет абсолютно никаких сомнений в том, что вы имеете в виду.

Ответ 14

Мы используем NULL для указателей и NULLCHAR для символов, используя

#define NULLCHAR '\0'