Можно ли предположить, что константа NULL равна нулю?
NULL
будет сравниваться равным 0
.
NULL
равно очень обычно шаблон с нулевым битом. NULL
может быть ненулевым битовым шаблоном, но в наши дни его не видели.
OP смешивает как минимум 4 вещи: NULL
, константа нулевого указателя , нулевой указатель , сравнение нулевого указателя с 0. C не определяет NULL-константу .
NULL
NULL
- это макрос ", который расширяется до константы нулевого указателя, определяемой реализацией" C17dr § 7.19 3
константа нулевого указателя
Выражение из целочисленной константы со значением 0 или такое выражение, приведенное к типу void
*, называется константой нулевого указателя . C17dr § § 6.3.2.3 3
Таким образом, тип константы нулевого указателя может быть int
, unsigned
, long
, ... или void *
.
Когда целое число 1 , константа нулевого указателя значение равно 0. Как указатель типа ((void *)0)
, его значение / кодировка не указана. Он повсеместно имеет битовую комбинацию нулей, но не указывается так.
Может быть много констант нулевого указателя . Все они сравниваются равными друг другу.
Примечание: размер константы нулевого указателя , когда она является целым числом, может отличаться от размера объекта указатель. Этой разницы в размерах часто можно избежать, добавляя L
или два суффикса при необходимости.
нулевой указатель
Если ноль константа указателя преобразуется в тип указателя, результирующий указатель, называемый нулевой указатель , гарантированно сравнивается с неравным указателем на любой объект или функцию. C17dr § 6.3.2.3 3
Преобразование нулевого указателя в другой тип указателя дает нулевой указатель этого типа. Любые два нулевых указателя должны сравниваться равными. C17dr § 6.3.2.3 4
Тип нулевой указатель - это некоторый указатель, либо указатель объекта, например, int *, char *
, либо указатель функции, например, int (*)(int, int)
или void *
. .
Значение нулевого указателя не указано. Он повсеместно имеет битовую комбинацию нулей, но не указывается так.
Все нулевой указатель сравниваются как равные, независимо от их кодировки.
сравнение нулевой указатель на 0
if(!ptr)
совпадает с if(!(ptr != 0))
. Когда указатель ptr
, который является нулевым указателем , сравнивается с 0, ноль преобразуется в указатель, нулевой указатель того же типа: int *
. Эти 2 нулевые указатели , которые могут иметь разные битовые комбинации, сравниваются как равные.
Поэтому, когда небезопасно предполагать, что NULL константа равна нулю?
NULL
может быть ((void*)0)
, а ее битовая комбинация может отличаться от нулей. Он сравнивается равным 0, как указано выше, независимо от его кодировки. Обсуждаемые сравнения указателей были обсуждены, а не целочисленные сравнения. Преобразование NULL
в целое число может не привести к целочисленному значению 0, даже если ((void*)0)
было всеми нулевыми битами.
printf("%ju\n", (uintmax_t)(uintptr_t)NULL); // Possible not 0
Обратите внимание, что это преобразование указателя на целое число, а не случай if(!ptr)
, где 0 был преобразован в указатель.
C spe c охватывает многие старые способы ведения дел и открыт для новых новых. Я никогда не сталкивался с реализацией, в которой NULL
не был битовым шаблоном со всеми нулями. Учитывая, что существует большой код, который предполагает, что NULL
- это все нулевые биты, я подозреваю, что только старые неизвестные реализации когда-либо использовали ненулевой битовый шаблон NULL
, и что NULL
может быть почти наверняка полностью нулевым битовым шаблоном.
1 Константа нулевого указателя равна 1) целому числу или 2) a void*
. «Когда целое число ... «относится к первому случаю, а не к преобразованию или преобразованию второго случая, как в (int)((void*)0)
.