Почему я не могу инициализировать массив переменного размера? - PullRequest
9 голосов
/ 09 июля 2011

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

В чем причина этого?Что плохого в этом:

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

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

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

Спасибо!

Ответы [ 6 ]

9 голосов
/ 09 июля 2011
  • Размер массива должен быть постоянным интегральным выражением.
  • Интегральный литерал - это постоянное интегральное выражение.(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)
    
5 голосов
/ 09 июля 2011

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

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

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

4 голосов
/ 09 июля 2011

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

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

4 голосов
/ 09 июля 2011

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

3 голосов
/ 09 июля 2011

Код не действителен в стандарте C ++.

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

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

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

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

0 голосов

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

int is1[2] = {1}

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...