Я спрашивал себя, могут ли эти строки кода привести к неопределенному поведению в C и C ++.
Я пытался ответить на каждую точку, читая, что стандарт говорит о подписке массива (C 6.5.6 — 8). Я не опубликовал весь абзац, потому что он довольно длинный.
Более того, если выражение
P
указывает на последний
элемент массива объекта, выражение(P)+1
указывает один за последним элементом
объект массива, и если выражениеQ
указывает один за последним элементом объекта массива,
выражение(Q)-1
указывает на последний элемент объекта массива. Если оба указателя
операнд и результат указывают на элементы одного и того же объекта массива или один за последним
элемент массива, при оценке не должно быть переполнения; в противном случае
поведение не определено. Если результат указывает на один последний элемент массива> object, он
не должен использоваться в качестве операнда унарного*
оператор, который оценивается.
1 int a[10];
2 int b = a[9]; // ok
3 int c = a[10]; // UB
4 int* d = (a + 10); // ok
5 int* e = &a[10]; // ok from C99 (& and [] are ignored, pointer is not deferenced), // UB in pre C99
6 int* f = &a[11]; // ok from C99, UB in pre c99
int* g = a;
7 int* h = g + 15; // ok
Я думаю, что те же ответы должны быть действительными для C ++
Являются ли эти строки действительными в C и C ++, я неправильно понял стандарт?
Ни 6, ни 7 не являются действительными, потому что они не выполняют арифметику указателей внутри существующего массива (включая указатель «один за другим»). Все остальное по сути правильно.
Только в C: учитывая, что a[i]
идентично *(a + i)
, а также &*p
всегда просто p
без оценки *p
, 5 всегда должно быть хорошо, хотя вы правы, что C89 не указывает это, и это было добавлено только в C99. (Это совсем не так в C ++, где операторы могут быть перегружены и нет упоминания о комбинировании &
а также *
.)
От n1570 (черновик до C11), в пункте 8 6.5.6 Аддитивные операторы:
[…] Если и операнд указателя, и результат [из P + N
] указывают на элементы одного и того же объекта массива или одного элемента после последнего элемента объекта массива, при оценке не должно быть переполнения; в противном случае поведение не определено. […]
C ++ содержит очень похожие формулировки (например, C ++ 11, 5.7 / 5).
Других решений пока нет …