2012-03-21 4 views
1

Можно создать дубликат:
C/C++: Array size at run time w/o dynamic allocation is allowed?время выполнения Const определить размер массива

В следующем листинге, явно размер buf определяется время выполнения постоянной j. Как компилятор генерирует код для размещения хранилища в стеке (не зная значения j во время компиляции)?

#include<iostream> 
#include<cstdlib> 

using namespace std; 

int main(){ 
    srandom(time(NULL));  
    int i = random(); 
    cout<< "random number: "<<i<<endl; 
    if(i%2==0) 
    i=2; 
    else 
    i=1; 
    const int j=i; 
    char buf[j]; 
    std::cout<<"size of buf array: "<<sizeof(buf)<<endl; 
    return 0; 
} 
+5

Позвольте мне угадать ... вы компилируете это с помощью g ++? Это нестандартное расширение, позволяющее VLA C99. C++ не позволяет их. Скомпилируйте с -pedantic и/или -Wall – Praetorian

+0

@ Prætorian: Yep yep –

+2

'objdump -d -S my_file', если вы хотите увидеть код, сгенерированный компилятором для этой строки. Кроме того, с '-pedantic' (при условии g ++):' предупреждение: ISO C++ запрещает массив переменной длины 'buf'' – AusCBloke

ответ

5

Я предполагаю, что вы используете gcc и, следовательно, расширение VLA. Это не стандартный C++, и он был удален из C++ 0x (1x).

Причина в том, что на самом деле это не все, что полезно, и что реализация C++ будет намного сложнее, чем одна из C из-за более сильной системы типов.

Действительно, если вы выделяете стек из массива неизвестного размера, вы в то же время пишете опасный код, который может очень сильно ударить стек. Если вы знаете размер, то это не проблема, иначе просто динамически распределите его. Есть, конечно, совершенно допустимые варианты использования, и это «хорошо иметь» функцию, но они в конечном итоге решили против нее.

Here is a good run down on the subject.

+0

Очень хорошая ссылка! – amirmonshi

+0

Сказать, что он был удален из C++ 11, очень вводит в заблуждение. Он НИКОГДА не был частью Standard C++. Он был предложен для включения в проект C++ 11, но отклонен. И этот поток в новостях отсутствует в полном объеме, ИМО, поскольку он полностью игнорирует различия в поведении между массивами POD (с C VLAs) и массивами нетривиальных объектов. –

0

Компилятор просто должен увеличить размер стека и указать переменную Buf на вновь созданном пространстве на стеке. Нет причин, по которым это невозможно сделать динамически с учетом размера во время выполнения. (Хотя это может быть неразумно делать с точки зрения программирования.)

+0

Нет причин, кроме того, что C++ требует, чтобы каждая переменная имела постоянный размер (формально постоянное целочисленное выражение *), известное во время компиляции. –

+0

@BenVoigt Да, но вопрос был: «Как может компилятор сделать это?» Ответ на этот вопрос прост. Все остальные обсуждения - важная информация, но не обязательно отвечают на вопрос о том, как это делает компилятор. –

4

Соответствующий компилятор C++ не принимает ваш код. Несмотря на то, что const, j не является постоянным выражением.

gcc принимает это в коде C++ как расширение (в соответствии с языковыми стандартами это разрешено только в коде C99). В принципе, он выделяет пространство в стеке для buf. Он (обычно) делает это путем вычитания некоторой суммы из текущего указателя стека. С точки зрения кода, который был создан, довольно тривиально иметь дело с тем, что он не является постоянным на типичной машине.

+0

@BenVoigt: Вы, конечно, знаете это, но мы говорим о C++, и C99, безусловно, не относится к нему. –

+0

@EdS: Конечно, но Джерри упомянул «gcc», который и есть. И команда 'gcc' является частью компилятора C gcc, что еще больше сбивает с толку. –

+0

@BenVoigt: Правда, хорошая точка. –

Смежные вопросы