Объем массива переменного размера

Всегда ли это будет работать так, как ожидалось?

char *x;
if (...) {
    int len = dynamic_function();
    char x2[len];

    sprintf(x2, "hello %s", ...);

    x = x2;
}

printf("%s\n", x);
// prints hello


Как компилятор (в моем случае GCC) реализует массивы переменного размера в C и C++?


person Max    schedule 17.01.2013    source источник
comment
Зависит от языка. Это расширение компилятора в C++.   -  person chris    schedule 18.01.2013
comment
Это не так. Поскольку вы объявляете переменную char x2[], ее пространство запрашивается из виртуальной памяти кучи/процесса и всегда остается неизменным. Когда вы пишете x = x2, вы указываете x на то же пространство памяти, что и x2, потому что x является указателем. edit но так будет не всегда, printf x без инициализации будет печатать мусор.   -  person Afonso Tsukamoto    schedule 18.01.2013
comment
Насколько я понимаю, x2 перестает существовать после оператора if, поэтому невозможно узнать, какой будет распечатка.   -  person Smash    schedule 18.01.2013
comment
Я думаю, это зависит от того, ожидаете ли вы, что это будет работать должным образом. Если вы это сделаете, то нет, это не сработает, как ожидалось.   -  person netcoder    schedule 18.01.2013
comment
Возможно, вы путаете VLA с нестандартной функцией alloca() — память, выделенная alloca(), действительно действительна до конца объемлющей области function и не зависит от локальных областей.   -  person Kerrek SB    schedule 18.01.2013


Ответы (3)


Нет. x2 является локальным для области действия оператора if, и вы получаете доступ к нему вне его с помощью указателя. Это приводит к неопределенному поведению.

Между прочим, VLA стали необязательными в C11 и никогда не были частью C++. Так что лучше этого избегать.

person P.P    schedule 17.01.2013
comment
С другой стороны, (очень) ограниченная форма VLA пробирается в следующий стандарт C++ ;-) - person Marc Glisse; 18.01.2013
comment
Немного неудобно в том смысле, что VLA добавили только в C99 и еще до того, как C99 стал массовым, его убрали из стандарта! - person P.P; 18.01.2013

Область действия объясняется здесь:

Переход или выход из области действия имени массива освобождает хранилище. Прыжки в прицел запрещены; вы получите сообщение об ошибке.

В вашем случае массив выходит за рамки.

person Jesse Good    schedule 17.01.2013

Нет, по двум причинам:

C++: код не является допустимым C++. Массивы в C++ должны иметь постоянный размер времени компиляции.

C: Нет, потому что массив существует только до конца блока, в котором он был объявлен, и, таким образом, разыменование x является поведением undefined.

Из C11, 6.2.4/2:

Если на объект ссылаются за пределами его времени жизни, поведение не определено.

А в 6.2.4/7 говорится, что массив переменной длины существует с момента его объявления до конца его охватывающей области:

Для такого объекта, который имеет тип массива переменной длины, его время жизни простирается от объявления объекта до тех пор, пока выполнение программы не выйдет из области действия объявления.

person Kerrek SB    schedule 17.01.2013