&(p->x); // is this undefined behavior?
Стандарт немного расплывчат в этом отношении:
[expr.ref] ... Выражение E1->E2 преобразуется в эквивалентную форму (*(E1)).E2;
[expr.unary.op] Унарный оператор *... результатом является значение lvalue, относящееся к объекту... на который указывает выражение.
В разделе нет явного упоминания UB. Правило в кавычках противоречит тому факту, что нулевой указатель не указывает ни на какой объект. Это можно интерпретировать так: да, поведение не определено.
[expr.unary.op] Результатом унарного оператора & является указатель на его операнд. ... если операнд является значением lvalue типа T, результирующее выражение является значением prvalue типа «указатель на T», результатом которого является указатель на обозначенный объект ([intro.memory]).
Опять же, обозначенного объекта не существует. Обратите внимание, что операнд lvalue ни в коем случае не преобразуется в rvalue, который определенно был бы UB.
Еще в 2000 г. возникла проблема CWG для уточнить, не определена ли косвенность через null. Предложенная резолюция (2004 г.), разъясняющая, что косвенное обращение через null является не UB, по-видимому, не была добавлена в стандарт на данный момент.
Однако, является ли это UB или нет, не имеет большого значения, поскольку вам не нужно этого делать. По крайней мере, результирующий указатель будет недействительным и, следовательно, бесполезным.
Если вы планировали преобразовать указатель в целое число, чтобы получить смещение элемента, в этом нет необходимости, поскольку вместо этого вы можете использовать макрос offsetof
из стандартной библиотеки, в которой нет UB.
&(p[1]); // undefined?
Здесь поведение явно не определено:
[expr.sub] ... Выражение E1[E2] идентично (по определению) выражению *((E1)+(E2)), за исключением того, что в случае операнда массива результатом является lvalue, если этот операнд является lvalue и xvalue в противном случае.
[expr.add] Когда выражение J, имеющее целочисленный тип, добавляется или вычитается из выражения P типа указателя, результат имеет тип P.
Если P оценивается как значение нулевого указателя, а J оценивается как 0 (не применяется)
В противном случае, если P указывает на элемент массива (не применяется)
В противном случае поведение не определено.
&(p[0]); // undefined?
В соответствии с предыдущими правилами применяется первый вариант:
Если P оценивается как значение нулевого указателя, а J оценивается как 0, результатом является значение нулевого указателя.
И теперь мы возвращаемся к вопросу о том, является ли косвенность через этот нуль UB. Смотрите начало ответа.
Тем не менее, не имеет большого значения. Нет необходимости писать это, так как это просто излишне сложный способ записи sizeof(int) * i
(где i
равно 1 и 0 соответственно).
person
eerorika
schedule
12.06.2020
p
, поэтому даже до того, как вы возьмете адрес, выполнениеp->x
будет таким же, как(*p).x
, то есть UB. - person cigien   schedule 12.06.2020