Неконстантное объявление массива - PullRequest
7 голосов
/ 21 марта 2011

Я учил себя программированию пару лет, и я был уверен, что если вам нужно объявление массива с переменным числом, вам нужно использовать malloc или new.

Сегодня я обнаружил, чтоон компилируется под g ++ версии 4.4.4, без предупреждений и ошибок:

#include <iostream>
using namespace std;

int main()
{
    int size_array;
    cin >> size_array;
    int iTable[size_array];

    for(int i=0;i < size_array;i++)
        iTable[i]=i*i;
    for(int i=0;i < size_array;i++)
        cout << iTable[i] << endl;

    return 0;
}

Также он прекрасно компилируется, если вы используете gcc (после изменения cout и cin с printf и scanf)

В Visual Studio этот код не компилируется, поскольку size_array не является константой.

Когда это было изменено?Это безопасный метод?

Ответы [ 8 ]

9 голосов
/ 21 марта 2011

Это функция C99 - VLA - которая не является частью стандарта c ++. Вы можете использовать его, если ваш компилятор поддерживает его, и вам не требуется переносимость. Если компилятор поддерживает его, он совершенно безопасен в использовании, но использование нестандартных функций - плохая привычка.

5 голосов
/ 21 марта 2011

Это расширение компилятора gcc , не стандартное.

2 голосов
/ 21 марта 2011

См. http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.20.

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

2 голосов
/ 21 марта 2011

Нет, это совсем не безопасно. Это может повредить ваш стек.

0 голосов
/ 15 октября 2012

Можно использовать эту функцию, если вы используете c99.

Вы должны быть очень осторожны с величиной размера. большое значение переполнит ваш стек, и ваш процесс может сойти с ума.

0 голосов
/ 22 июня 2011

Вы можете получить эту функциональность в C или C ++ с помощью alloca (_alloca в Windows). std :: vector НЕ является заменой: он размещается в куче с помощью new, который вызывает malloc, что потенциально дорого.

Есть веская причина, по которой вы можете захотеть иметь массив, длина которого определяется во время выполнения, размещенного в стеке: он действительно быстрый. Предположим, у вас есть цикл, который выполняется часто, но имеет массив, который зависит от чего-то во время выполнения (скажем, размер вашего виджета Canvas). Вы не можете просто жестко закодировать число: ваша программа потерпит крах, когда мы все получим мониторы Retina-дисплея с 36-дюймовым разрешением 300 точек на дюйм и пиксели [2400] больше не безопасны. Но вы не хотите нового, или ваш цикл попадет в malloc и становится медленным.

Хотя для больших массивов может быть лучше иметь std :: vector, который является статическим по отношению к функции и только когда его размер будет изменен (увеличен), так как ваш стек имеет ограниченный размер.

(см. http://msdn.microsoft.com/en-us/library/wb1s57t5(VS.71).aspx)

0 голосов
/ 21 марта 2011

Существует расширение GCC, имитирующее массивы переменной длины C99.Это не стандарт C ++.

Однако, , даже если у вас отключено , опубликованный код может скомпилироваться.Стандарт не требует диагностики для этого случая: это неопределенное поведение, а не ошибка.

В действительно очевидных случаях компилятор может запретить вам писать это, но в противном случае он может позволить вам потерпеть неудачу вмир.

Вывод: не обманывайтесь сборником.Это все еще плохо и неправильно.

0 голосов
/ 21 марта 2011

Это зависит от того, пишете ли вы на C или C ++. Я предполагаю, что C, как и для C ++, лучше использовать std :: vector, а не массив.

В Си это зависит от того, какую версию вы используете. Если и только если вы используете стандартный компилятор C99, то массив может взять свой размер из переменной во время выполнения, как вы делаете здесь, иначе размер должен быть определен во время компиляции. Visual Studio не поддерживает динамический массив - см. MSDN

C ++ использует стандарт C89, поэтому требует, чтобы размер был установлен во время компиляции.

Так что в вашем случае вам нужно посмотреть, какие флаги вы передали компилятору.

Как отметил @Eric, код на C ++, поэтому работающий компилятор использует нестандартное расширение, поэтому для gnu я бы добавил flags для обеспечения соблюдения стандарта, например. -ansi или -std = c ++ 98 и -pedantic

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