В C, как представляется, различия между различными значениями нуля - NULL
, NUL
и 0
.
Я знаю, что символ ASCII '0'
оценивается как 48
или 0x30
.
NULL
Указатель обычно определяется как:
#define NULL 0
Или
#define NULL (void *)0
Кроме того, есть NUL
персонаж, '\0'
который, кажется, оценивает 0
также.
Есть ли случаи, когда эти три значения не могут быть равны?
Это также верно для 64-битных систем?
NUL
не существует в стандартном языке или библиотеке C (или в C ++, насколько я знаю). Нулевой символ иногда называется NUL, но это C или C ++, обычно он называется просто'\0'
.Ответы:
Примечание. Этот ответ относится к языку C, а не к C ++.
Нулевые указатели
Целочисленный константный литерал
0
имеет разные значения в зависимости от контекста, в котором он используется. Во всех случаях это все еще целочисленная константа со значением0
, это просто описано по-разному.Если указатель сравнивается с константным литералом
0
, то это проверка, чтобы увидеть, является ли указатель нулевым указателем. Это0
затем называется постоянной нулевой указатель. Стандарт C определяет, что0
приведение к типуvoid *
является как нулевым указателем, так и константой нулевого указателя.Кроме того, для удобства чтения макрос
NULL
предоставляется в заголовочном файлеstddef.h
. В зависимости от вашего компилятора может быть возможно#undef NULL
и переопределить его в нечто дурацкое.Поэтому вот несколько допустимых способов проверить наличие нулевого указателя:
NULL
определяется для сравнения равным нулевому указателю. Это реализация, определяемая тем, что является фактическим определениемNULL
, при условии, что это допустимая константа нулевого указателя.0
это еще одно представление константы нулевого указателя.Это
if
утверждение неявно проверяет «не 0», поэтому мы обращаемся к значению «0».Ниже приведены недействительные способы проверки нулевого указателя:
Для компилятора это не проверка на нулевой указатель, а проверка на равенство двух переменных. Это может сработать, если mynull никогда не изменится в коде, а константа оптимизации компилятора сложит 0 в оператор if, но это не гарантируется, и компилятор должен выдать хотя бы одно диагностическое сообщение (предупреждение или ошибка) в соответствии со стандартом C.
Обратите внимание, что это пустой указатель на языке Си. Это не имеет значения в базовой архитектуре. Если в базовой архитектуре значение нулевого указателя определено как адрес 0xDEADBEEF, то компилятор должен разобраться в этом беспорядке.
Таким образом, даже в этой забавной архитектуре следующие способы все еще являются допустимыми способами проверки на нулевой указатель:
Ниже приведены недействительные способы проверки нулевого указателя:
так как они рассматриваются компилятором как обычные сравнения.
Нулевые символы
'\0'
определяется как нулевой символ - это символ со всеми битами, установленными в ноль. Это не имеет ничего общего с указателями. Однако вы можете увидеть что-то похожее на этот код:проверяет, указывает ли указатель строки на нулевой символ
проверяет, указывает ли строковый указатель на ненулевой символ
Не путайте их с нулевыми указателями. Просто потому, что битовое представление одно и то же, и это допускает некоторые удобные перекрестные случаи, на самом деле это не одно и то же.
Кроме того,
'\0'
является (как и все символьные литералы) целочисленной константой, в данном случае со значением ноль. Таким образом,'\0'
он полностью эквивалентен0
целочисленной константе без приукрашивания - единственное отличие заключается в том, что намерение, которое оно передает читателю-человеку («Я использую это как нулевой символ»).Ссылки
См Вопрос 5.3 comp.lang.c FAQ для более. Смотрите этот PDF для стандарта C. Ознакомьтесь с разделами 6.3.2.3. Указатели, пункт 3.
источник
ptr
с нулевыми битами . Это не такmemcmp
, но это сравнение с использованием встроенного оператора. Одна сторона является константой нулевого указателя'\0'
, а другая сторона является указателем. Как и с двумя другими версиями сNULL
и0
. Эти трое делают одно и то же.0xDEADBEEF
по - прежнему является указатель NULL, независимо от того , что нравится его битовый внешний вид, и он будет по- прежнему считается равнымNULL
,0
,\0
и все другими постоянными формами указателя нуля.ptr == '\0'
.Похоже, что некоторые люди неправильно понимают разницу между NULL, '\ 0' и 0. Итак, чтобы объяснить, и в попытке избежать повторения сказанного ранее:
Постоянное выражение типа
int
со значением 0 или выражение этого типа, приведенное к типу,void *
является константой нулевого указателя , которая при преобразовании в указатель становится нулевым указателем . Стандартом гарантируется сравнение неравного с любым указателем на любой объект или функцию .NULL
макрос, определенный как константа нулевого указателя .\0
это конструкция, используемая для представления нулевого символа , используемой для завершения строки.Нулевой символ является байт , который имеет все биты , установленные в 0.
источник
Все три определяют значение нуля в разных контекстах.
Эти три всегда разные, когда вы смотрите на память:
Я надеюсь, что это проясняет это.
источник
sizeof('\0')
и удивляйся.Если NULL и 0 эквивалентны как константы нулевого указателя, что я должен использовать? в списке часто задаваемых вопросов C также решается эта проблема:
источник
"нулевой символ (NUL)" проще всего исключить.
'\0'
это буквальный символ. В C он реализованint
так, как и 0, что соответствуетINT_TYPE_SIZE
. В C ++ символьный литерал реализован какchar
, то есть 1 байт. Это обычно отличается отNULL
или0
.Следующий,
NULL
указывается значение указателя, которое указывает, что переменная не указывает на какое-либо адресное пространство. Если оставить в стороне тот факт, что он обычно реализован в виде нулей, он должен быть в состоянии выразить полное адресное пространство архитектуры. Таким образом, в 32-разрядной архитектуре NULL (вероятно) является 4-байтовым, а в 64-разрядной архитектуре - 8-байтовым. Это до реализации С.Наконец, литерал
0
имеет типint
, который имеет размерINT_TYPE_SIZE
. Значение по умолчаниюINT_TYPE_SIZE
может отличаться в зависимости от архитектуры.Apple написал:
Википедия 64-битная :
редактировать : Добавлено больше на литерале персонажа.
Приведенный выше код возвращает 4 на gcc и 1 на g ++.
источник
'\0'
это не 1-байтовое значение. Это символьный литерал, который является целочисленным константным выражением, поэтому если можно сказать, что он имеет размер, то это размерint
(который должен быть не менее 2 байтов). Если вы мне не верите, оценитеsizeof('\0')
и убедитесь сами.'\0'
,0
И0x0
все полностью эквивалентны.sizeof('\0')
компилятор C ++.A-L NUL, он заканчивается строкой.
Ноль L-два указывает ни на что.
И я поставлю золотой бык
Это не три-L NULLL.
Как вы справляетесь с NUL?
источник
Одна хорошая вещь, которая помогает мне, когда я начинаю с C (взято из Expert C Programming от Linden)
Один 'l' nul и два 'l' null
Запомните этот небольшой стих, чтобы вспомнить правильную терминологию для указателей и нулевого ASCII:
Символ ASCII с битовой комбинацией нуля называется «NUL». Специальное значение указателя, которое означает, что указатель нигде не является «NULL». Эти два термина не являются взаимозаменяемыми по смыслу.
источник
NUL
управляющий код , такой какBEL
,VT
,HT
, иSOT
т.д. , и , таким образом , имеет макс. 3 персонажа.«NUL» не равно 0, но относится к символу ASCII NUL. По крайней мере, так я это видел. Нулевой указатель часто определяется как 0, но это зависит от среды, в которой вы работаете, и спецификации используемой операционной системы или языка.
В ANSI C пустой указатель указывается как целочисленное значение 0. Так что любой мир, где это не так, не соответствует ANSI C.
источник
В
0x00
таблице ASCII байт со значением - это специальный символ, называемыйNUL
илиNULL
. В C, поскольку вы не должны встраивать управляющие символы в исходный код, это представляется в строках C с экранированным 0, т\0
. Е.Но истинный NULL не является значением. Это отсутствие ценности. Для указателя это означает, что указателю не на что указывать. В базе данных это означает, что в поле нет значения (это не то же самое, что сказать, что поле пустое, 0 или заполнено пробелами).
Фактическое значение данной системы или формат файла базы данных используется для представления
NULL
не обязательно0x00
.источник
NULL
не гарантируется равным 0 - его точное значение зависит от архитектуры. Большинство основных архитектур определяют это(void*)0
.'\0'
всегда будет равняться 0, потому что именно так байт 0 кодируется в символьном литерале.Я не помню, требуется ли компиляторам C использовать ASCII - если нет, то
'0'
может не всегда равняться 48. Несмотря на это, вряд ли вы когда-нибудь столкнетесь с системой, которая использует альтернативный набор символов, такой как EBCDIC, если вы не работаете над очень неясные системы.Размеры различных типов будут отличаться в 64-битных системах, но целочисленные значения будут одинаковыми.
Некоторые комментаторы выражают сомнение в том, что NULL будет равно 0, но не будет нулевым. Вот пример программы вместе с ожидаемым выходом в такой системе:
Эта программа может напечатать:
источник
(void *) 0 равно NULL, а '\ 0' представляет конец строки.
источник