Подтвердить что ты не робот

Уменьшение указателя вне границ; приращение его в границы

Происходит ли следующее поведение undefined в строке 4 и/или 5:

#include <stdio.h>
int main(void)
{
  char s[] = "foo";
  char * p = s - 1;      /* line 4 */
  printf("%s\n", p + 1); /* line 5 */
  return 0;
}
4b9b3361

Ответ 1

Происходит ли следующее поведение undefined в строке 4 и/или 5:

Да, строка 4 undefined поведение, поскольку указатель не указывает на границы массива или один за границами массива. Хотя верно, чтобы указать один за границами массива, вы не можете разыменовать этот элемент.

Соответствующий раздел в черновик проекта c99 6.5.6 Аддитивные операторы, пункт 8:

Когда выражение, которое имеет целочисленный тип, добавляется или вычитается из указателя, result имеет тип операнда указателя. [...] Если оба операнда указателя и результат указывают на элементы одного и того же объекта массива или один за последним элементом объекта массива, оценка не должна приводить к переполнению; , поведение undefined.

В конце абзаца говорится, что вы не должны относиться к одному из последних элементов:

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

Ответ 2

Уменьшение указателя за пределами границ массива undefined.

C99 standard, пункт 6.5.6 в пункте 8, отчасти,

Когда выражение, которое имеет целочисленный тип, добавляется или вычитается из указателя, result имеет тип операнда указателя.... Если оба указателя операнд и результат указывают на элементы одного и того же объекта массива или один за последним элемент объекта массива, оценка не должна приводить к переполнению; в противном случае поведение не определено.

Итак, ваша строка 4 вызывает поведение undefined, так как результат не находится ни в массиве, ни в конце его.

Ответ 3

Да, строка 4 - это поведение undefined!

C99 6.5.6 Аддитивные операторы, раздел 8

Когда выражение, которое имеет целочисленный тип, добавляется или вычитается из указателя, result имеет тип операнда указателя. Если операнд указателя указывает на элемент объект массива и массив достаточно велик, результат указывает на смещение элемента от исходный элемент такой, что разность индексов результирующих и исходных элементов массива равна целочисленному выражению. Другими словами, если выражение P указывает на элемент i-th объекта массива, выражения (P) + N (эквивалентно, N + (P)) и (P) - N (где N имеет значение N) указывают на, соответственно, элементы i+n-th и i−n-th объекта массива, если они существуют. Более того, если выражение P указывает на последний элемент объекта массива, выражение (P) + 1 указывает один за последним элементом объекта массива, а если выражение Q указывает один за последним элементом массива объект, выражение (Q) - 1 указывает на последний элемент объекта массива. Если оба операнда указателя и результат указывают на элементы одного и того же объекта массива или один за последним элементом объекта массива, оценка не должна приводить к переполнению; в противном случае поведение undefined. Если результат указывает один за последним элементом объекта массива, он не должен использоваться как операнд унарного оператора *, который оценивается.