Почему я не могу инициализировать массив переменного размера?

GCC не дает ошибок при инициализации массива переменного размера, пока переменная является const, но когда это не так, она не будет компилироваться.

в чем причина этого? Что плохого в том, чтобы делать:

int size = 7;
int test[size] = {3, 4, 5};

это не будет компилироваться вообще, но если я не инициализирую test [], то он компилируется! Это не имеет никакого смысла для меня, потому что, насколько я знаю, кадр стека должен быть сделан, чтобы соответствовать этому массиву в соответствии с его размером (7 ints) независимо от того, что (что означает целочисленные литералы, которые я использую, на самом деле не имеют никакого значения, если я не ошибаюсь), так какая разница, инициализирую я его или нет?

еще один из моих сумасшедших вопросов дизайна C++...

спасибо!

6 ответов


  • размер массива должен быть постоянным интегральным выражением.
  • интегральный литерал-это постоянное интегральное выражение. (int arr[5];)
  • постоянная интегральная переменная, инициализированная постоянным выражением, является постоянным выражением. (const int j = 4; const int i = j; int a[i];)

  • постоянная переменная, инициализированная непостоянным выражением, не является постоянным выражением

     int x = 4;  // x isn't constant expression because it is not const
     const int y = x; //therefore y is not either
     int arr[y]; //error)
    

некоторые компиляторы позволяют это, если вы используете const int size = 7;. Теоретически компилятор мог бы выяснить, что это постоянный размер, но это не сделать это.


от http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html "автоматические массивы переменной длины разрешены в ISO C99, и как расширение GCC принимает их в режиме C90 и в C++. "

ваша программа недействительна на c++ вообще, и gcc компилирует ее как "расширение". Вероятно, вам придется спросить авторов gcc, почему они решили реализовать таким образом.


Это на самом деле больше похоже на сумасшедший вопрос дизайна C99, так как массивы переменной длины-это функция от C99, которую gcc позволяет в C++ как расширение.

в C99, 6.7.8 / 3 говорит " тип объекта, который будет инициализирован ... не является типом массива переменной длины", поэтому gcc просто использовал то же правило для его расширения, что и C99.

документ обоснования C99 ничего не говорит о том, почему VLA не может быть инициализирован. Я могу предположить, что это может быть, потому что риска избыточных элементов в инициализаторе, если значение, предусмотренное для размера, оказывается меньше инициализатора. Но я не знаю.


код недопустим в стандартном языке C++.

по состоянию на (8.3.4.1) на стандарт C++, размер массива должен быть константным выражением

массивы переменной длины не разрешены в C++, потому что C++ предоставляет для этого std::vector.

массив переменной длины был функцией, введенной в C99 после того, как C++ разветвился от стандарта C на основе c98. C++ уже был std::vector обеспечить функциональность переменной длины массивы поэтому стандарт C++ никогда не допускал массивы переменной длины в качестве части стандарта.

Если ваш компилятор поддерживает это, это через расширение компилятора. Скомпилируйте с-pedantic option, и он уведомит вас об этом с предупреждением о том, что это запрещено ISO C++


Я не уверен в намерениях дизайнеров gcc, когда они реализовали это расширение, но одна из возможных причин, почему расширение gcc работает так:

int is1[2] = {1}

компилирует без предупреждения, разумно предположить, что пользователь хочет {1,0}

int is2[1] = {1,2};

компилируется с предупреждением, что должен делать компилятор?

int i;
cin >> i;
int is3[i] = {1,2}

ага, предупредить или не предупредить?