Отрицательный индекс массива в C

На форуме были и другие вопросы/ответы по отрицательному массиву в C, но я бы попросил ответить на них для 32-битного компилятора: если у нас есть определенный массив int test_array[5] = {1,2,3,4,5};

то какие следующие операторы должны возвращать test_array[20], test_array[-2], test_array[-32764], test_array[4294967700] (значение больше, чем может вместить 32 бит), *(a-32764) и т. д.

Принуждает ли компилятор возвращать какое-либо фиксированное значение в случае, если индекс выходит за пределы объявленного диапазона?


person Bleamer    schedule 15.11.2011    source источник


Ответы (3)


Доступ к массиву за пределами его границ приводит к неопределенному поведению (UB).
Индекс -ve не является допустимым индексом и приводит к неопределенному поведению.

Неопределенное поведение означает, что буквально все может случиться. Если вам повезет, ваша программа рухнет и проблема будет обнаружена. Если вам не повезет, код все время работает нормально, и однажды все рухнет.
Поэтому всегда избегайте написания чего-либо. код, вызывающий неопределенное поведение.

Принуждает ли компилятор возвращать какое-либо фиксированное значение в случае, если индекс выходит за пределы объявленного диапазона?

НЕТ
Об этом должен позаботиться программист. Стандарту не требуется, чтобы компилятор давал какие-либо указания/предупреждения об этом. Стандарт просто определяет его как UB.

Кроме того, стандарт определяет все следующие сценарии, вызывающие неопределенное поведение:

  • Добавление или вычитание указателя в объект массива и целочисленный тип или сразу за ним приводит к результату, который не указывает на один и тот же объект массива или сразу за ним.
  • Добавление или вычитание указателя в объект массива и целочисленный тип или сразу за ним дает результат, который указывает сразу за объектом массива и используется в качестве операнда вычисляемого unary * operator.
  • Нижний индекс массива находится вне диапазона, даже если объект явно доступен с данным индексом (как в выражении lvalue a[1][7] при объявлении int a[4][5]).
person Alok Save    schedule 15.11.2011

Это неопределенное поведение, когда вы его пишете, поскольку вы обращаетесь к массиву за пределами границ.

Однако отрицательные индексы не обязательно означают неопределенное поведение. Следующий код хорошо определен:

int test_array[5] = {1,2,3,4,5};
int *p = test_array + 1;
int i = p[-1];//i now has the value 1

Это эквивалентно:

int i = *(p-1);
person David Heffernan    schedule 15.11.2011

Доступ к элементам за пределами массива является неопределенным поведением.

Кроме того, создание указателя, указывающего на элемент вне массива, за исключением (несуществующего) одного за последним, также является неопределённым поведением. Доступ к последнему является неопределенным поведением (существование указателя в порядке)

int arr[42] = {0};
int *ptr = arr;
ptr += 41; /* ok, ptr points to the last element of arr */
*ptr;      /* ok */
ptr += 1;  /* ok, ptr points to one-past-the-last */
*ptr;      /* UB */
ptr += 1;  /* UB */

ptr = arr;
ptr -= 1;  /* UB */
person pmg    schedule 15.11.2011