В первые дни C ++, когда он был прикреплен к C, вы не могли использовать NULL, как это было определено как (void*)0
. Вы не можете присвоить NULL любому указателю, кроме void*
, что делает его бесполезным. В те дни было принято, что вы использовали 0
(ноль) для нулевых указателей.
До сих пор я продолжал использовать ноль в качестве нулевого указателя, но те, кто вокруг меня, настаивают на использовании NULL
. Лично я не вижу никакой выгоды в присвоении имени ( NULL
) существующему значению - и так как мне также нравится проверять указатели как значения истинности:
if (p && !q)
do_something();
тогда использование нуля имеет больше смысла (например, если вы используете NULL
, вы не можете логически использовать p && !q
- вам нужно явно сравнить с NULL
, если вы не предполагаете, что NULL
это ноль, и в этом случае зачем использовать NULL
).
Есть ли объективная причина предпочесть ноль, а не NULL (или наоборот), или все это просто личные предпочтения?
Изменить: я должен добавить (и изначально хотел сказать), что с RAII и исключениями, я редко использую указатели нуля / NULL, но иногда они вам все еще нужны.
Ответы:
Вот что говорит Страуструп: FAQ по стилю и технике C ++
Тем не менее, не парься мелочи.
источник
Есть несколько аргументов (один из которых является относительно недавним), которые, по моему мнению, противоречат позиции Бьярне по этому вопросу.
Использование
NULL
позволяет выполнять поиск по его использованию, а также подчеркивает, что разработчик хотел использоватьNULL
указатель, независимо от того, интерпретируется ли он компиляторомNULL
или нет.Пример, который все цитируют:
Тем не менее, по крайней мере, на мой взгляд, проблема с вышесказанным не в том, что мы используем NULL для константы нулевого указателя, а в том, что у нас есть перегрузки 'foo', которые принимают совершенно разные аргументы. Параметр должен быть
int
тоже, так как любой другой тип приведет к неоднозначному вызову и, следовательно, сгенерирует полезное предупреждение компилятора.Даже в отсутствие C ++ 0x сегодня существуют инструменты, которые проверяют,
NULL
что используется для указателей, а также0
для целочисленных типов.std::nullptr_t
тип.Это новейший аргумент таблицы. Проблема
0
иNULL
активно решается для C ++ 0x, и вы можете гарантировать, что для каждой реализации, которая обеспечиваетNULL
, самое первое, что они сделают, это:Для тех , кто использует ,
NULL
а не0
изменение будет улучшение безопасности типов с практически без усилий - если что - то может поймать несколько ошибок , где они используютсяNULL
для0
. Для тех, кто использует0
сегодня .... эээ ... ну, надеюсь, они хорошо знают регулярные выражения ...источник
#include
и сохраните его в полной безопасности.#define NULL nullptr
кажется опасным. Что бы там ни было, во многих устаревших кодах NULL используется для вещей, отличных от 0. Например, дескрипторы часто реализуются как некоторый целочисленный тип, и установка их вNULL
нередки. Я даже видел злоупотребления, такие как использованиеNULL
для установкиchar
нулевого терминатора.NULL
самом деле неверны. Многие API давно используютсяNULL
с дескрипторами, и это фактически является документированным использованием со многими из них. Не прагматично внезапно ломать их и заявлять, что они делают это неправильно.Используйте NULL. NULL показывает ваше намерение. То, что это 0 - это деталь реализации, которая не должна иметь значения.
источник
Я всегда использую:
NULL
для указателей'\0'
для персонажей0.0
для поплавков и парных разрядовгде 0 будет хорошо. Это вопрос сигнализации намерения. Тем не менее, я не анальный об этом.
источник
Я давно перестал использовать NULL в пользу 0 (как и большинство других макросов). Я сделал это не только потому, что хотел как можно больше избегать макросов, но и потому, что NULL, похоже, стал чрезмерно использоваться в коде C и C ++. Кажется, он используется всякий раз, когда требуется значение 0, а не только для указателей.
На новых проектах я помещаю это в заголовок проекта:
Теперь, когда приходят компиляторы, совместимые с C ++ 0x, все, что мне нужно сделать, это удалить эту строку. Приятным преимуществом этого является то, что Visual Studio уже распознает nullptr в качестве ключевого слова и выделяет его соответствующим образом.
источник
Мораль этой истории. Вы должны использовать NULL, когда имеете дело с указателями.
1) Он объявляет ваше намерение (не заставляйте меня искать весь ваш код, пытаясь выяснить, является ли переменная указателем или каким-либо числовым типом).
2) В определенных вызовах API, которые ожидают переменных аргументов, они будут использовать NULL-указатель, чтобы указать конец списка аргументов. В этом случае использование «0» вместо NULL может вызвать проблемы. На 64-битной платформе вызов va_arg требует 64-битного указателя, но вы будете передавать только 32-битное целое число. Мне кажется, что ты полагаешься на другие 32-битные, которые обнуляются для тебя? Я видел некоторые компиляторы (например, icpc от Intel), которые не так хороши - и это приводило к ошибкам во время выполнения.
источник
NULL
возможно, не переносимо и не безопасно. Там могут быть платформы, которые все еще#define NULL 0
(в соответствии с часто задаваемыми вопросами Страуструпа: должен ли я использовать NULL или 0? Цитируется по верхнему вопросу, и он входит в число первых результатов поиска). По крайней мере, в более старом C ++0
имеет особое концептуальное значение в контексте указателя. Вы не должны думать конкретно о битах. Также обратите внимание , что в разных контекстах целочисленных (short
,int
,long long
) «sizeof(0)
» будет отличаться. Я думаю, что этот ответ немного ошибочен.NULL
вместо(char *)0
,(const char *)0
или(struct Boo *)0
или(void *)0
или независимо от того, чтобы выражающего намерение более четко. - без (на мой взгляд) слишком громоздким)Если я правильно помню, NULL определяется по-разному в заголовках, которые я использовал. Для C он определен как (void *) 0, а для C ++ - как 0. Код выглядел примерно так:
Лично я все еще использую значение NULL для представления нулевых указателей, это делает очевидным, что вы используете указатель, а не какой-то целочисленный тип. Да, внутренне значение NULL по-прежнему равно 0, но оно не представлено как таковое.
Кроме того, я не полагаюсь на автоматическое преобразование целых чисел в логические значения, но явно сравниваю их.
Например, предпочитаете использовать:
скорее, чем:
Достаточно сказать, что все это исправлено в C ++ 11, где можно просто использовать
nullptr
вместоNULL
, а такжеnullptr_t
это тип anullptr
.источник
Я бы сказал, что история говорила, и те, кто высказывался в пользу использования 0 (ноль), ошибались (включая Бьярна Страуструпа). Аргументы в пользу 0 были в основном эстетическими и «личными предпочтениями».
После создания C ++ 11 с его новым типом nullptr некоторые компиляторы начали жаловаться (с параметрами по умолчанию) на передачу 0 функциям с аргументами-указателями, поскольку 0 не является указателем.
Если бы код был написан с использованием NULL, можно было бы выполнить простой поиск и замену по базе кода, чтобы вместо этого сделать его nullptr. Если вы застряли с кодом, написанным с использованием выбора 0 в качестве указателя, его гораздо утомительнее обновить.
И если вам нужно прямо сейчас написать новый код для стандарта C ++ 03 (и вы не можете использовать nullptr), вам действительно следует просто использовать NULL. В будущем вам будет намного проще обновляться.
источник
Я обычно использую 0. Мне не нравятся макросы, и нет никакой гарантии, что какой-то сторонний заголовок, который вы используете, не определяет NULL как нечто странное.
Вы можете использовать объект nullptr, предложенный Скоттом Мейерсом и другими, пока C ++ не получит ключевое слово nullptr:
Google "nullptr" для получения дополнительной информации.
источник
(void*)0
если она компилируется как код C), просто требует проблем и не должна использоваться.NULL
над(type *)0
является возможность поиска, как мне кажется. В противном случае кажется ненужным запутывание, если бы это не было языком C. Я лично думаю, что идиома распространенияNULL
повсеместно заслуживает смерти.NULL
это бесполезный макрос на мой взгляд. Бритве Оккама нужно здесьОднажды я работал на машине, где 0 был действительным адресом, а NULL был определен как специальное восьмеричное значение. На этой машине (0! = NULL), поэтому такой код, как
не будет работать, как вы ожидаете. Вы должны были написать
Хотя я полагаю, что в настоящее время большинство компиляторов определяют NULL как 0, я все еще помню урок тех лет назад: NULL не обязательно равен 0.
источник
Я думаю, что стандарт гарантирует, что NULL == 0, так что вы можете сделать либо. Я предпочитаю NULL, потому что это документирует ваши намерения.
источник
foo.bar_ptr = (Bar *) 0
выражает намерение гораздо яснее, чемfoo.bar_ptr = NULL
. Эта привычка также дает возможность компилятору отлавливать для вас ошибки в заблуждении. Для меняfoo.bar_ptr = 0
выражает намерение, а также использует,NULL
если я знаю, чтоfoo.bar_ptr
это указатель.Использование 0 или NULL будет иметь тот же эффект.
Однако это не означает, что они оба являются хорошими практиками программирования. Принимая во внимание, что нет различий в производительности, выбор низкоуровневого варианта вместо независимой / абстрактной альтернативы является плохой практикой программирования. Помогите читателям вашего кода понять ваш мыслительный процесс .
NULL, 0, 0.0, '\ 0', 0x00 и все остальные означают одно и то же, но являются разными логическими объектами в вашей программе. Они должны быть использованы как таковые. NULL - это указатель, 0 - это количество, 0x0 - это значение, чьи биты интересны и т. Д. Вы не назначали бы '\ 0' для указателя, независимо от того, компилируется он или нет.
Я знаю, что некоторые сообщества поощряют демонстрацию глубоких знаний об окружающей среде, нарушая условия окружающей среды. Ответственные программисты, однако, создают поддерживаемый код и не допускают такой практики в свой код.
источник
Странно, никто, включая Страуструп, не упомянул это. В то время как много говорить о стандартах и эстетику никто не заметил , что это опасно использовать
0
вNULL
вместо «s, например, в списке переменных аргументов по архитектуре гдеsizeof(int) != sizeof(void*)
. Как и Stroustroup, я предпочитаю0
по эстетическим соображениям, но нужно быть осторожным, чтобы не использовать его там, где его тип может быть неоднозначным.источник
0
условии , необходимо указать , какие0
вы имеете в виду - например(int *)0
,(char *)0
,(const char *)0
или(void *)0
или(unsigned long long) 0
или любой другой . Это, на мой взгляд, выражает намерение гораздо яснее, чемNULL
.NULL
означает.(void *)
когда могу использовать точный тип. Я намеренно привел пример (обычно) 64-битного целого числа в списке, потому что он аналогичен регистру указателя. Кроме того, если мои воспоминания о том, что старый C ++ определенNULL
как0
точный (прошло много лет с тех пор, как я программировал на C ++), то мы не увидим улучшения в правильности программы. Более новый стандарт C ++, к счастью, предоставляетnullptr
ключевое слово, поэтому мы можем избавиться от этогоNULL
уродства и всей полемики при написании более нового C ++.(void*)
был абстрагирован доNULL
. И наNULL
самом деле выражает намерение довольно четко большую часть времени. И я думаю, что вы помните неправильно. Не уверен насчет стандартов, но на практике я верю, что так и было(void*)0
. И да,nullptr
это хороший преттификатор, хотя это одно иNULL
то же - указание нулевого указателя без указания типа.nullptr
несет то же сообщениеNULL
, что и только в отношении выражения намерения, которое вы упомянули в самом начале. (Предварительная обработкаNULL
на современныхgcc
урожаях__null
, что бы это ни было).Я стараюсь избежать всего вопроса, используя ссылки на C ++, где это возможно. Скорее, чем
Вы часто можете писать
Конечно, это не всегда работает; но нулевые указатели могут быть чрезмерно использованы.
источник
На этом я с Страуструпом :-) Так как NULL не является частью языка, я предпочитаю использовать 0.
источник
В основном личные предпочтения, хотя можно привести аргумент, что NULL делает совершенно очевидным, что объект является указателем, который в настоящее время ни на что не указывает, например
IIRC, стандарт не требует, чтобы NULL был равен 0, поэтому использование того, что определено в <stddef.h>, вероятно, лучше всего подходит для вашего компилятора.
Другим аспектом аргумента является то, следует ли использовать логические сравнения (неявное приведение к bool) или проверку чистоты по NULL, но это также сводится к удобочитаемости.
источник
Я предпочитаю использовать NULL, поскольку это ясно, что ваше намерение - это значение, представляющее указатель, а не арифметическое значение. Тот факт, что это макрос, вызывает сожаление, но, поскольку он так широко укоренился, нет никакой опасности (если кто-то не делает что-то действительно сумасшедшее). Хотелось бы, чтобы это было ключевое слово с самого начала, но что вы можете сделать?
Тем не менее, у меня нет проблем с использованием указателей в качестве истинных ценностей самих по себе. Как и в случае с NULL, это укоренившаяся идиома.
C ++ 09 добавит конструкцию nullptr, которая, я думаю, давно назрела.
источник
Я всегда использую 0. Не по какой-либо реальной причине, просто когда я впервые изучал C ++, я прочитал что-то, что рекомендовало использовать 0, и я просто всегда делал это таким образом. В теории может возникнуть путаница с удобочитаемостью, но на практике я никогда не сталкивался с такой проблемой в тысячах человеко-часов и миллионах строк кода. Как говорит Страуструп, на самом деле это вопрос личной эстетики, пока стандартом не станет nullptr.
источник
Кто-то сказал мне однажды ... Я собираюсь переопределить NULL на 69. С тех пор я не использую его: P
Это делает ваш код довольно уязвимым.
Редактировать:
Не все в стандарте идеально. Макрос NULL - это определяемая реализацией константа нулевого указателя C ++, не полностью совместимая с макросом C NULL, которая, помимо скрытого типа, неявно преобразует его в бесполезный и подверженный ошибкам инструмент.
NULL ведет себя не как нулевой указатель, а как литерал O / OL.
Скажите, следующий пример не смущает:
Это из-за всего этого, в новом стандарте появляется std :: nullptr_t
Если вы не хотите ждать нового стандарта и хотите использовать nullptr, используйте хотя бы приличный, такой как предложенный Мейерсом (см. Комментарий jon.h).
источник
NULL
является четко определенной частью стандарта C ++. Позволяя людям, которым нравится переопределять стандартные макросы, редактировать код в вашем проекте, делает ваш код «уязвимым»; использованиеNULL
неНу, я утверждаю, что вообще не использую 0 или NULL указатели, когда это возможно.
Их использование рано или поздно приведет к ошибкам сегментации в вашем коде. По моему опыту, и указатели на Gereral является одним из крупнейших источников ошибок в C ++
также, это приводит к операторам if-not-null во всем вашем коде. Гораздо приятнее, если вы всегда можете положиться на действительное состояние.
Почти всегда есть лучшая альтернатива.
источник
0
) является полезным для отладки. Намного лучше, чем разыменование случайного мусора и получение того, кто знает, какой результат.Установка указателя на 0 не совсем понятна. Особенно, если вы приехали на языке, отличном от C ++. Это включает в себя как C, так и Javascript.
Я недавно разобрался с некоторым кодом:
virtual void DrawTo(BITMAP *buffer) =0;
для чисто виртуальной функции в первый раз. Я думал, что это будет волшебная спячка на неделю. Когда я понял, что это просто установка указателя функции на a
null
(поскольку виртуальные функции - это просто указатели функций в большинстве случаев для C ++), я пнул себя.virtual void DrawTo(BITMAP *buffer) =null;
было бы менее запутанным, чем это взволнование без правильного расстояния между моими новыми глазами. На самом деле, мне интересно, почему C ++ не использует строчные буквы так
null
же, как он использует строчные ложные и истинные сейчас.источник