Если я напишу
int zero = 0;
void *p1 = (void *)0;
void *p2 = (void *)(int)0;
void *p3 = (void *)(0 /*no-op, but does it affect the next zero?*/, 0);
void *p4 = (void *)zero; // For reference, this is a pointer to address zero
void *p5 = 0; // For reference, this is a null pointer
void *p6 = NULL; // For reference, this is a null pointer
void *p7 = nullptr; // For reference, this is a null pointer (C++11)
static const int static_zero_1 = 0; // Is this a literal zero when used?
static const int static_zero_2 = 1 - 1; // No "literals 0" per se... is it?
void *p8 = (void *)static_zero_1; // I have seen weird substitution rules...
void *p9 = (void *)static_zero_2; // do they apply for NULL too?
какой из p1
, p2
, а также p3
(редактировать: я добавил p8
а также p9
) было бы нулевые указатели (Т.е. == NULL
, может или не может быть адрес ноль), и какие из них будут указатели с адресом ноль (может или не может быть == NULL
)?
Если ответ различается в C и C ++, что в каждом из них?
p1
а также p2
нулевые указатели; p3
определяется реализация,
и может быть что-то еще. (Оператор запятой не может быть частью
постоянное выражение. И отображение непостоянное
целое значение 0 для указателя определяется реализацией.) C является
идентичен C ++ здесь.
p8
а также p9
оба являются нулевыми указателями в C ++, но не в C.
Что касается вашего комментария static_zero_2
, здесь нет
требование на любом языке, чтобы присутствовал буквальный ноль,
в любом месте. g ++ определяет NULL
как встроенный компилятор __null
,
например, и вы можете использовать (1 - 1)
, или же '\0'
или любой другой
константное выражение с оценкой 0.
И чтобы завершить ответ Энди с C:
6.3.2.3. Указатели
1 Указатель на void может быть преобразован в или из указателя на любой незавершенный объект
тип. Указатель на любой неполный или тип объекта может быть преобразован в указатель на void
и обратно снова; результат должен сравниваться равным исходному указателю.3 Ан целочисленное константное выражение со значением
0
, или такое выражение приведено к типу
void *
, называется константа нулевого указателя.
55) Если константа нулевого указателя преобразуется в
тип указателя, результирующий указатель, называемый нулевым указателем, гарантированно сравнивает неравные
на указатель на любой объект или функцию.
Так что любой целочисленное константное выражение который оценивает 0
является константой нулевого указателя и может быть преобразована в NULL
указатель. Эффективно в вашем примере все указатели, кроме p4
, p8
а также p9
нулевые указатели. p4
, p8
а также p9
не должны быть нулевыми указателями, так как их инициализация не является константным выражением, поскольку содержит переменные (даже если const
Квалифицированный).
Вот еще один ответ о NULL
в C ++, Для записи.
какой из
p1
,p2
, а такжеp3
будут нулевые указатели?
В C ++ 11 все они. В соответствии с пунктом 4.10 / 1 стандарта C ++ 11:
константа нулевого указателя является целочисленным константным выражением (5.19) prvalue целочисленного типа, которое оценивается как
ноль или тип значенияstd::nullptr_t
, […]
Поэтому, согласно терминологии Стандарта, все, что является постоянная (интегральное) выражение и оценивает 0
это константа нулевого указателя (не нулевой указатель, еще). Единственное, которое не является константным выражением, которое оценивает 0
или тип значения nullptr_t
в вашем примере это zero
потому что это не постоянное выражение.
Абзац продолжается:
Константа нулевого указателя может быть преобразована в тип указателя;
Результатом является значение нулевого указателя этого типа и отличается от любого другого значения указателя объекта или
тип указателя на функцию. Такое преобразование называется преобразование нулевого указателя. Два значения нулевого указателя
один и тот же тип должен сравниваться равным.
Так что в вашем примере все указатели, кроме p4
являются значения нулевого указателя и сравнивать равных между собой.