Стандарт 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++ содержали четкий нормативный язык, который больше не присутствует. Старые, неопределенные вопросы, подобные этому, не актуальны.