2009-04-10 6 views
47

Я использую C++ в течение нескольких лет, и сегодня я увидел некоторый код, но как это может быть совершенно законным?Допустимый размер массива во время выполнения без динамического распределения?

int main(int argc, char **argv) 
{ 
    size_t size; 
    cin >> size; 
    int array[size]; 
    for(size_t i = 0; i < size; i++) 
    { 
     array[i] = i; 
     cout << i << endl; 
    } 

    return 0; 
} 

Составлено под GCC.

Как определить размер во время выполнения без new или malloc?

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

Даже Deitel's C++ Как программировать с. 261 в рамках общей ошибки программирования 4.5:

Только константы могут использоваться для объявления размера автоматических и статических массивов.

Просветите меня.

+2

отмечают, что DMA означает «прямой доступ к памяти» - Я думаю, что вы спрашиваете о динамическом распределении – 2009-04-10 10:32:14

+2

C или C++? Выбери один_. –

+1

Опять же, выберите один: C или C++. Этот вопрос явно и только о C; не должно быть тега C++. –

ответ

49

Это действительно на C99.

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

Обратите внимание, что это отличается от malloc и new. gcc выделяет массив в стеке, точно так же, как int array[100], просто корректируя указатель стека. Выделение кучи не выполняется. Это очень похоже на _alloca.

+7

Я столкнулся с этим же сценарием в файле в нашей базе кода, который был написан несколько месяцев назад.Я был сбит с толку, как и остальная команда, о том, почему он скомпилирован. В нашей ситуации размер массива вычислялся до объявления массива (что тоже нельзя допускать?). В любом случае проблема вышла. Любой, кто мог бы ответить, почему это законно, становится популярным. Если вы когда-нибудь в Сиэтле, дайте мне знать. У меня есть поп-пирог для вас. –

+0

Можете ли вы предоставить некоторую информацию/ссылку о том, как стек внутри работает в этом случае? Означает ли это некоторые накладные расходы во время выполнения? – balki

+1

@balki Накладные расходы незначительны, так как они в основном увеличивают/уменьшают указатель стека. Поведение стека может быть по существу идентичным нормальному случаю, если вы сохраните исходный указатель стека в начале функции. –

7

Это valid только в C99. В следующий раз вы можете попробовать проверить код в reliable compiler.

4

Действительно C99, это недействительно C++. Это один из немногих различий между этими двумя языками.

+2

Я предполагаю, что это будет поддерживаться в C++ 0x –

+0

Не в соответствии с разделом 8.3.4 проекта стандарта. – 2009-04-10 10:47:41

+2

он никогда не будет включен в C++ 1x: D, но будем надеяться, что dynarray войдет. Мне бы это понравилось. так что вы можете сделать dynarray a (some_size); и эффективно распределить его, возможно, с компилятором hax, например _alloca и так далее. –

18

Это известно как VLA (массивы переменной длины). Он стандартный в c99, но gcc разрешает его в C++-коде как расширение. Если вы хотите отклонить код, попробуйте поэкспериментировать с параметрами -std=standard, -ansi и -pedantic.

0

Вы можете придать размер массиву динамически, если вы используете компилятор Dev-Cpp. Я пробовал его и не получил никаких ошибок, но на визуальных компиляторах Visual C++ и Visual Studio это невозможно. Я думаю, причина в том, что dev-C++ присваивает положительное число неинициализированному int , и когда мы приводим его число, оно заменяется данным. , но, возможно, другие компиляторы дают null неинициализированным переменным.

+0

Большинство компиляторов не присваивают ничего неинициализированным локальным переменным, они, как правило, будут удерживать все, что было в памяти, которую они занимают, до тех пор, пока они не будут назначены программой. По-видимому, Dev-C++, на которую вы ссылаетесь, является IDE поверх MinGW, который включает в себя порт GCC в качестве компилятора. Как отмечалось в других ответах, VLA не являются стандартными C++, но некоторые компиляторы (включая g ++) поддерживают их в любом случае. – jerry

+0

Dev-C++ не является компилятором. Также нет Visual Studio. Dev-C++ использует GCC/G ++ в качестве своего компилятора, в то время как Visual Studio использует cl (внутренний компилятор Microsoft). Dev-C++ и Visual Studio сами по себе являются интегрированными средами разработки (IDE). Это важное различие. Dev-C++ не «присваивает» что-либо. Компилятор делает это. – Elkvis

-1

Массивы переменной длины (VLAs) поддерживаются в стандарте C++ 14, который был недавно принят и ожидает публикации.

+1

VLA по-прежнему не являются частью стандарта. Существует [dynarray] (http://en.cppreference.com/w/cpp/container/dynarray) TS, но пока он не ратифицирован. – Jason

0

Этот код работает в компиляторе GNU GCC.

#include<bits/stdc++.h> 

int main(int argc, char **argv) 

{ 
    size_t size; 

    std:: cin >> size; 

    int array[size]; 

    for(size_t i = 0; i < size; i++) 

{ 

array[i] = i; 

     std:: cout << i; 

} 

    return 0; 
}