Создает ли указатель один за концом указателя не-массива, не полученного из унарного оператора & неопределенного поведения в С++ 17? - программирование
Подтвердить что ты не робот

Создает ли указатель один за концом указателя не-массива, не полученного из унарного оператора & неопределенного поведения в С++ 17?

Стандарт C++ 17, кажется, говорит, что целое число может быть добавлено только к указателю, если указатель относится к элементу массива или, в качестве специального исключения, указатель является результатом унарного оператора &:

8.5.6 [expr.add], описывающий добавление указателя:

Когда выражение с интегральным типом добавляется или вычитается из указателя, результат имеет тип операнда указателя. Если выражение P указывает на элемент x [i] объекта массива x с n элементами, выражения P + J и J + P (где J имеет значение j) указывают на (возможно-гипотетический) элемент x [i + j], если 0 ≤ я + j ≤ n; в противном случае поведение не определено.

Эта цитата включает ненормативную сноску:

Объект, который не является элементом массива, считается принадлежащим одноэлементному массиву для этой цели; см. 8.5.2.1

который ссылается на 8.5.2.1 [expr.unary.op], обсуждая унарный оператор &:

Результат унарного оператора & является указателем на его операнд... Для целей арифметики указателя (8.5.6) и сравнения (8.5.9, 8.5.10) объект, который не является элементом массива , адрес которого берется таким образом, считается принадлежащим массиву с одним элементом типа T.

Ненормативная сноска, похоже, немного вводит в заблуждение, так как в разделе, который он ссылается, описывается поведение, характерное для результата унарного оператора &. По-видимому, ничто не позволяет рассматривать другие указатели (например, из не-массива new) как одноэлементные массивы.

Это, по-видимому, предполагает:

void f(int a) {
    int* z = (new int) + 1; // undefined behavior
    int* w = &a + 1; // ok
}

Является ли это надзором за изменения, внесенные для C++ 17? Я что-то пропустил? Есть ли причина, что "правило одноэлементного массива" предоставляется только для унарного оператора &?

Примечание. Как указано в заголовке, этот вопрос относится к C++ 17. Стандарт C и предыдущие версии стандарта C++ содержали четкий нормативный язык, который больше не присутствует. Старые, неопределенные вопросы, подобные этому, не актуальны.

4b9b3361

Ответ 1

Да, это похоже на ошибку в стандарте.

int* z = (new int)+1; // undefined behavior.
int* a = new int;
int* b = a+1; // undefined behavior, same reason as 'z'
&*a; // seeming noop, but magically makes '*a' into an array of one element!
int* c = a+1; // defined behavior!

это довольно смешно.

8.5.2.1 [expr.unary.op]

[...] объект, который не является элементом массива, адрес которого берется таким образом, считается принадлежащим массиву с одним элементом типа T

один раз "благословленный" по 8.5.2.1, объект представляет собой массив из одного элемента. Если вы не благословляете его, вызывая & по крайней мере один раз, он никогда не был благословлен 8.5.2.1 и не является массивом одного элемента.