C ++ динамический размер статического массива головоломка - PullRequest
7 голосов
/ 08 июня 2011

Пытаясь объяснить кому-то, почему статический массив C ++ не может быть динамически изменен, я обнаружил, что gcc не согласен со мной.Как следующий код даже компилируется, учитывая, что измерение argc из array не известно во время компиляции?

#include <iostream>
int main(int argc, char* argv[]) {
    int array[argc];
    for(int i = 0; i < argc; i++) array[i] = argv[i][0];
    for(int i = 0; i < argc; i++) std::cout << i << ": " << char(array[i]) << std::endl;
    //for(int i = 0; i < 100; i++) { std::cout << i << " "; std::cout.flush(); array[i] = 0; }
    return 0;
}

Я проверил это с помощью gcc 4.2.1, и указал -Wall, не получая столько грязного взгляда от компилятора.Если я раскомментирую последний цикл, я получаю ошибку segfault, когда назначаю массив [53] .

. Ранее я размещал защитные массивы до и после объявления array и заполнил их нулями, уверенными, что программа должна уничтожать часть своего стека, но gcc переупорядочил переменные в стеке, так что я не смог наблюдать искажения данных.

Очевидно, яне пытаясь заставить этот код "работать".Я просто пытаюсь понять, почему gcc даже думает, что может скомпилировать код.Будем очень благодарны за любые подсказки или объяснения.

Обновление: Спасибо всем за ваши полезные и смехотворно быстрые ответы!

Ответы [ 5 ]

10 голосов
/ 08 июня 2011

Массивы переменной длины (VLA) являются частью C99 и поддерживаются gcc в течение длительного времени:

http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

Обратите внимание, что использование VLA в C90 и C ++код нестандартен, но поддерживается gcc как расширение.

6 голосов
/ 09 июня 2011

Это Массив переменной длины , который является частью стандарта C99.Однако он не является частью C ++.

Вы также можете использовать функцию alloca, которая также не является стандартной C ++, но широко поддерживается:

int main(int argc, char* argv[])
{
    int* array = (int*) alloca( argc * sizeof(int) );
    array[0] = 123;
    // array automatically deallocated here. Don't call free(array)!
}
3 голосов
/ 08 июня 2011

Они называются массивами переменной длины (доступны с C99) и могут быть объявлены только как автоматические переменные - попробуйте поставить static впереди, и компилятор отклонит его. Это просто включает увеличение указателя стека с помощью переменной, а не с постоянным смещением, не более того.

До введения массивов переменной длины распределение объектов переменного размера в стеке выполнялось с помощью функции alloca.

2 голосов
/ 09 июня 2011

Массивы в C ++ не могут быть изменены, за исключением использования константного выражения.Массивы, измеренные неконстантно, являются либо частью C99, либо ужасным расширением, навязанным нам GCC.Вы можете избавиться от большей части дерьма GCC, используя флаг -pedantic при компиляции кода C ++.

2 голосов
/ 08 июня 2011

Массивы на основе стеков переменного размера являются расширением G ++ и вполне допустимы. Они, однако, не стандартные. В большинстве реализаций массивы на основе стеков действительно могут иметь различные размеры, но стандарт этого не требует.

...