Объявление массива отрицательной длины

Что происходит в C, когда вы создаете массив отрицательной длины?

Например:

int n = -35;

int testArray[n];

for(int i = 0; i < 10; i++)
    testArray[i]=i+1;

Этот код скомпилируется (и не выдаст никаких предупреждений с включенным параметром -Wall), и кажется, что вы можете назначить testArray[0] без проблем. Назначение прошлого, которое дает либо ошибку сегментации, либо недопустимую ошибку инструкции, и чтение чего-либо из массива говорит «Прервать ловушку» (я не знаком с этим). Я понимаю, что это несколько академично и (надеюсь) никогда не возникнет в реальной жизни, но есть ли какой-то особый способ, который стандарт C говорит для обработки таких массивов, или он варьируется от компилятора к компилятору?


person jonmorgan    schedule 23.09.2010    source источник
comment
Я думаю, что в конце оператора for есть непреднамеренная точка с запятой (;)...   -  person Arun    schedule 24.09.2010


Ответы (3)


Это поведение undefined, потому что оно нарушает ограничение «должен»:

C99 §6.7.5.2:

Если размер является выражением, которое не является целочисленным константным выражением... ...каждый раз, когда он оценивается, он должен иметь значение больше нуля.

person caf    schedule 24.09.2010
comment
Спасибо! Это именно то, что я искал. - person jonmorgan; 24.09.2010
comment
+1, точно ответ. Но меня очень разочаровывает, что компиляторы еще не могут провести статический анализ такого кода и выдать хотя бы предупреждение. Я тестировал также с clang и -analyse, не лучше. - person Jens Gustedt; 24.09.2010

Неопределенное поведение, я считаю, хотя не цитируйте меня по этому поводу.

Это дает ошибку error: size of array 'testArray' is negative в gcc:

int testArray[-35];

хотя, как вы видели:

int n = -35;
int testArray[n];

не выдает ошибку даже с обоими -Wall и -W.

Однако, если вы используете флаг -pedantic, gcc предупредит, что ISO C90 запрещает массив переменной длины.

person Lie Ryan    schedule 23.09.2010
comment
Что он на самом деле делает? Я предполагаю, что он интерпретирует его как неподписанный, поэтому вы получаете (MAX_INT-35) - person Martin Beckett; 24.09.2010
comment
@Martin Beckett: поскольку это неопределенное поведение, компиляторы могут делать что угодно, даже если это неразумное поведение, поскольку выделение массива отрицательной длины - это бессмыслица для компиляции. Если бы мне разрешили изменить дизайн C, я бы сделал объявление длины массива и индексировал бы «целое число без знака», и компилятор должен был бы выдавать ошибку типа, когда «целое число со знаком» используется для операций длины или индексации. - person Lie Ryan; 24.09.2010
comment
вопрос был помечен C99, поэтому аспект массива переменной длины в порядке с точки зрения стандартов. - person Jens Gustedt; 24.09.2010
comment
@MartinBeckett, это просто сходит с ума sizeof(testArray) == -35 * sizeof(int); - person OwnageIsMagic; 18.11.2020

Сообщение об ошибке Visual Studio для компиляции, вы можете используйте -1, чтобы сказать пустой массив. Он ожидает int, и вы передаете int, поэтому ошибки компилятора нет.

person yadab    schedule 24.09.2010