Ответ 1
Я использую '\0'
для nul-character и NULL
для указателей, потому что в обоих случаях это яснее.
BTW, как 0
, так и '\0'
являются int
в C, и каждый из них будет преобразован в char
при сохранении в переменной char
.
Время от времени я сталкиваюсь с проблемой связи с другими программистами, когда мы говорим о NULL. Теперь NULL может быть
указатель NULL
символ NUL
пустой элемент данных в какой-то базе данных.
NUL кажется самым запутанным. Это символ ASCII 0x00.
Я обычно использую '\ 0' в своем коде для его представления. Некоторые разработчики в моей группе
предпочитают просто использовать 0, и пусть компилятор неявно передает его в char.
Что вы предпочитаете использовать для NUL? и почему?
Я использую '\0'
для nul-character и NULL
для указателей, потому что в обоих случаях это яснее.
BTW, как 0
, так и '\0'
являются int
в C, и каждый из них будет преобразован в char
при сохранении в переменной char
.
Мне нравится предопределенный макрос NULL, поскольку он сохраняет семантическое значение, а не какое-либо другое использование числа 0.
Есть много английских слов, которые пишутся или говорят одинаково, но которые имеют разные значения. Как на английском языке, используйте контекст, в котором происходит обсуждение, чтобы направлять вас к намеченному значению.
END_OF_STRING глупо, поскольку это дополнительное косвенное отношение, которое просто путает новых читателей (каждый, кто не сразу распознает "\ 0", должен отходить от клавиатуры).
Еще одна вещь: я думаю, что разница между нулевым значением и пустым значением чрезвычайно важна при обсуждении моделирования данных. Это особенно актуально при обсуждении строк C-стиля или полей базы данных с возможностью NULL. Там огромная разница между тем, кто говорит вам: "У меня нет имени" и "Меня зовут".
Если я правильно помню, большинство компиляторов 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 обсуждается с этой проблемой.
@BKB:
Я вижу смысл в его совете, но "NULL" дает понять, что контекст является указателем. Это похоже на использование "0.0" для значений с плавающей запятой, как "\ 0" при работе с символами. (Аналогично, я предпочитаю видеть 0, если в арифметическом контексте используется char.)
Bjarne далее утверждает в этот FAQ, что NULL #defined как 0 в любом случае, поэтому стандартный код не должен иметь проблемы с ним. Я согласен с тем, что нотация all-caps является уродливой, но нам придется подождать до 0x (где nullptr будет доступно в качестве ключевого слова.)
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.)
NULL для баз данных, NIL для кода.
Мне очень нравится
#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.
Хотя, в целом, я бы советовал использовать именованные константы, это одно исключение. Для меня, определяя:
#define NULL 0
#define END_OF_STRING '\0'
имеет такое же значение, как и определение:
#define SEVEN 7
который не является. И да, я знаю, что NULL уже определен компилятором, но я никогда не использую его. Для указателей 0; для символов, '\ 0'. Более длинный не всегда означает более выразительный.
Для связи я использую NULL. Если я работаю с разработчиком, который не может понять концепцию NULL для разных типов данных, тогда я был бы заинтересован.
Для реализации это конкретный случай. Числа равны 0 (постфиксирован f для с плавающей запятой), указатели NULL, а символьные строки - 0.
Системы, которые не используют двоичный код 0 для NULL, становятся все труднее найти. Они также имеют различные проблемы с переносимостью. Зачем? Поскольку в этих системах ни memset, ни calloc не могут очистить структуру, содержащую указатели правильно.
const char END_OF_STRING = '\0';
Итак, когда вы говорите:
str[i] = END_OF_STRING;
или
if (*ptr == END_OF_STRING)
нет абсолютно никаких сомнений в том, что вы имеете в виду.
Мы используем NULL для указателей и NULLCHAR для символов, используя
#define NULLCHAR '\0'
Относительно связанных: Slashdot недавно рассказывал о разделе comp.lang.c
FAQ о нулевых указателях, который я нашел довольно интересным.