В чем разница между NULL, ' ' и 0
В C, по-видимому, существуют различия между различными значениями нуля -- NULL,NUL и 0.
я знаю, что символ ASCII '0' значение 48 или 0x30.
The NULL указатель обычно определяется как:
#define NULL 0
или
#define NULL (void *)0
кроме того, есть NUL символ '' который, кажется, оценить 0 как хорошо.
бывают ли случаи, когда эти три значения могут не быть равным?
это также верно на 64-битных системах?
11 ответов:
Примечание: этот ответ относится к языку C, а не c++.
Нулевые Указатели
целочисленных констант
0имеет различные значения в зависимости от контекста, в котором он используется. Во всех случаях это все еще целочисленная константа со значением0, это просто описано по-разному.если указатель сравнивается с констант
0, то это проверка, чтобы увидеть, если указатель является пустой указатель. Это0затем называется константой нулевого указателя. Стандарт C определяет, что0приведение к типуvoid *- это как нулевой указатель, нулевой указатель константу.кроме того, чтобы помочь читаемости, макрос
NULLсодержится в заголовочном файлеstddef.h. В зависимости от вашего компилятора можно#undef NULLи переопределить его на что-то необычное.таким образом, вот несколько допустимых способов проверить значение null указатель:
if (pointer == NULL)
NULLопределяется для сравнения равным нулевому указателю. Это реализация определяется тем, что фактическое определениеNULL, если это допустимая константа нулевого указателя.if (pointer == 0)
0- это еще одно представление константы нулевого указателя.if (!pointer)этой
ifутверждение неявно проверяет "не 0", так у нас наоборот, что означает "0".ниже приведены недопустимые способы проверки нулевой указатель:
int mynull = 0; <some code> if (pointer == mynull)для компилятора это не проверка нулевого указателя, а проверка равенства двух переменных. Это может работа, если mynull никогда не изменяется в коде, а константа оптимизации компилятора складывает 0 в Оператор if, но это не гарантируется, и компилятор должен создать хотя бы одно диагностическое сообщение (предупреждение или ошибка) в соответствии со стандартом C.
обратите внимание, что это нулевой указатель на языке C. Оно не имеет значения на базовую архитектуру. Если базовая архитектура имеет нулевое значение указателя, определенное как адрес 0xDEADBEEF, то компилятор должен разобраться в этом беспорядке.
таким образом, даже на этой забавной архитектуре, следующие способы по-прежнему являются допустимыми способами проверки нулевого указателя:
if (!pointer) if (pointer == NULL) if (pointer == 0)ниже приведены недопустимые способы проверки нулевого указателя:
#define MYNULL (void *) 0xDEADBEEF if (pointer == MYNULL) if (pointer == 0xDEADBEEF)как они рассматриваются компилятором как обычные сравнения.
Нулевые Символы
''определяется как нулевой символ - то есть символ со всеми битами, равными нулю. Это не имеет ничего общего с указателями. Однако вы можете увидеть что-то похожее на этот код:if (!*string_pointer)проверяет, указывает ли строковый указатель на нулевой символ
if (*string_pointer)проверяет, указывает ли строковый указатель на ненулевой символ
не путайте их с нулевыми указателями. Просто потому, что битовое представление одно и то же, и это позволяет использовать некоторые удобные перекрестные случаи, они на самом деле не одно и то же.
кроме того,
''является (как и все символьные литералы) целочисленной константой, в данном случае со значением ноль. Так что''полностью эквивалентно неприкрашенному0целочисленная константа-единственная разница в намерение что он передает человеческому читателю ("я использую это как нуль характер.").ссылки
посмотреть вопрос 5.3 комп.ленг.с чаво дополнительные. Смотрите это pdf для стандарта C. Проверьте разделы 6.3.2.3 указатели, пункт 3.
похоже, что некоторые люди неправильно понимают, в чем разница между NULL, '\0' и 0. Так, чтобы объяснить, и в попытке избежать повторения сказанного ранее:
постоянное выражение типа int со значением 0, или выражение этого типа, приведенное к типу void * является константа нулевого указателя, который при преобразовании в указатель становится нулевой указатель. Это гарантируется стандартом для сравнения неравный для любого указателя на любой объект или функция.
NULL - это макрос, определенный в качестве константа нулевого указателя.
'\0' - это конструкция, используемая для представления символ, используется для завершения строки.
A символ - это байт, который имеет все биты установлены в 0.
все три определяют значение нуля в разных контекстах.
- контекст указателя-NULL используется и означает, что значение указателя равно 0, независимо от того, является ли оно 32-битным или 64-битным (один случай 4 байта другие 8 байтов нулей).
- контекст строки-символ, представляющий нулевую цифру, имеет шестнадцатеричное значение 0x30, тогда как символ NUL имеет шестнадцатеричное значение 0x00 (используется для завершения строк).
эти три всегда разные когда вы смотрите на память:
NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit) NUL - 0x00 or 0x0000 (ascii vs 2byte unicode) '0' - 0x20Я надеюсь, что это проясняет его.
если NULL и 0 эквивалентны как константы нулевого указателя, что я должен использовать? в списке часто задаваемых вопросов C также рассматривается эта проблема:
C программисты должны понимать, что
NULLи0заменимы в указатель контексты, и что распаковать0вполне приемлемо. Любое использование NULL (в отличие от0) следует считается мягким напоминанием о том, что указатель задействован; программисты не должно зависеть от его (либо для их собственное понимание или компилятора) для различения указателя0' s от integer0' s.это только в контексте указатель
NULLи0эквивалентны.NULLдолжны не используется, когда другой вид0is требуется, даже если это может сработать, потому что это посылает неправильный стилистический посыл. (Кроме того, ANSI позволяет определениеNULLбудет((void *)0), который не будет работать на все в не-указателе контексты.) В в частности, не используйтеNULLкогда ASCII нулевой символ (NUL) желательна. Предоставьте свое собственное определение#define NUL ''если вы должны.
в чем разница между NULL, ‘\0’ и 0
" нулевой символ (NUL) " легче всего исключить.
''- это символьный литерал. В 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может отличаться в зависимости от архитектуры.Яблоко написал:
64-разрядная модель данных, используемая Mac OS X, известна как"LP64". Это общая модель данных, используемая другими 64-разрядными системами UNIX от Sun и SGI, а также 64-разрядной Linux. Модель данных LP64 определяет примитивные типы следующим образом:
- ints 32-бит
- длинные 64-битные
- длинные-длинные также 64-бит
- указатели 64-битные
Википедия 64-бит:
компилятор Microsoft VC++ использует модель LLP64.
64-bit data models Data model short int long long long pointers Sample operating systems LLP64 16 32 32 64 64 Microsoft Win64 (X64/IA64) LP64 16 32 64 64 64 Most Unix and Unix-like systems (Solaris, Linux, etc.) ILP64 16 64 64 64 64 HAL SILP64 64 64 64 64 64 ?Edit: Добавлена дополнительная информация о символьном литерале.
#include <stdio.h> int main(void) { printf("%d", sizeof('')); return 0; }приведенный выше код возвращает 4 на gcc и 1 на g++.
a one-L NUL, он заканчивает строку.
два-L NULL не указывает ни на что.
и я поставлю золотого быка
что нет трех-L НУЛЛ.
" NUL " не является 0, но относится к символу ASCII NUL. По крайней мере, я видел, как он используется. Нулевой указатель часто определяется как 0, но это зависит от условий работы и спецификацию независимо от операционной системы и используемого языка.
в ANSI C нулевой указатель задается как целочисленное значение 0. Поэтому любой мир, где это не так, не соответствует ANSI C.
один хороший кусок, который помогает мне при запуске с C (взятый из экспертного программирования C Линденом)
Nul с одной " л "и двумя" л " нуль
запомните эту маленькую рифму, чтобы вспомнить правильную терминологию для указателей и ASCII zero:
The one "l" NUL ends an ASCII string, The two "l" NULL points to no thing. Apologies to Ogden Nash, but the three "l" nulll means check your spelling.символ ASCII с битовым шаблоном нуля называется "NUL". Специальное значение указателя, которое означает, что точки указателя нигде не являются "нулевыми". Эти два термина не являются взаимозаменяемыми в значение.
байт со значением 0x00 является в таблице ASCII специальным символом, называемым "NUL"или " NULL". В C, поскольку вы не должны вставлять управляющие символы в исходный код, это представлено в строках C с экранированным 0, т. е. "\0".
но истинный нуль-это не значение. Это отсутствие ценности. Для указателя это означает, что указателю нечего указывать. В базе данных это означает, что в поле нет значения (что не то же самое, что сказать поле пустое, 0 или заполнено пробелами).
The фактический значение, которое данный формат файла системы или базы данных использует для представления NULL, не обязательно 0x00.
NULLне гарантируется 0 -- его точное значение зависит от архитектуры. Большинство основных архитектур определяют его как(void*)0.
''всегда будет равно 0, потому что именно так байт 0 кодируется в символьном литерале.Я не помню, требуются ли компиляторы C для использования ASCII - если нет,
'0'не всегда может равняться 48. Несмотря на это, маловероятно, что вы когда-либо столкнетесь с системой, которая использует альтернативный набор символов, такой как EBCDIC, если вы не работаем над очень непонятных систем.размеры различных типов будут отличаться в 64-разрядных системах, но целочисленные значения будут одинаковыми.
некоторые комментаторы выразили сомнение, что NULL будет равно 0, но не быть ноль. Вот пример программы, наряду с ожидаемым выходом на такой системе:
#include <stdio.h> int main () { size_t ii; int *ptr = NULL; unsigned long *null_value = (unsigned long *)&ptr; if (NULL == 0) { printf ("NULL == 0\n"); } printf ("NULL = 0x"); for (ii = 0; ii < sizeof (ptr); ii++) { printf ("%02X", null_value[ii]); } printf ("\n"); return 0; }эта программа может печатать:
NULL == 0 NULL = 0x00000001
Comments