Это нулевые указатели или они указывают на адрес 0?
Если я напишу
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++, что в каждом из них?
3 ответа
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 целочисленного типа, которое оценивается как ноль или prvalue типа
std::nullptr_t
, [...]
Следовательно, согласно терминологии Стандарта, все, что является постоянным (интегральным) выражением и оценивается как 0
является константой нулевого указателя (пока не нулевым указателем). Единственное, которое не является константным выражением, которое оценивает 0
или тип значения nullptr_t
в вашем примере это zero
потому что это не постоянное выражение.
Абзац продолжается:
Константа нулевого указателя может быть преобразована в тип указателя; результат является нулевым значением указателя этого типа и отличается от любого другого значения указателя объекта или типа указателя функции. Такое преобразование называется преобразованием нулевого указателя. Два значения нулевого указателя одного типа должны сравниваться одинаково.
Так что в вашем примере все указатели, кроме p4
являются нулевыми значениями указателя и сравниваются равными между собой.