c++ - чайников - указатель на указатель




Размер массива C++, зависящий от параметра функции, вызывает ошибки компиляции (5)

У меня есть простая функция, в которой массив объявляется с размером в зависимости от параметра, который является int.

    void f(int n){
        char a[n];
    };

    int main() {
        return 0;
    }

Этот фрагмент кода отлично компилируется на GNU C ++ , но не на MSVC 2005.

Я получаю следующие ошибки компиляции:

    .\main.cpp(4) : error C2057: expected constant expression
    .\main.cpp(4) : error C2466: cannot allocate an array of constant size 0
    .\main.cpp(4) : error C2133: 'a' : unknown size

Что я могу сделать, чтобы исправить это?

(Мне интересно сделать эту работу с MSVC, не используя new / delete)


Ваш метод выделения из стека - расширение g ++. Чтобы выполнить эквивалент в MSVC, вам необходимо использовать _alloca:

char *a = (char *)_alloca(n);

Вы используете что-то, что не является стандартом. На самом деле это стандартный C, но не C ++. Как это странно!

Объясняя немного больше, массивы стека времени выполнения не являются частью C ++, но являются частью C99, последнего стандарта для C. Вот почему некоторые компиляторы его получают, а другие - нет. Я бы рекомендовал воздержаться от его использования, чтобы избежать проблем с совместимостью компилятора.

Альтернативная реализация функциональности будет использовать новые и удалить, как опубликовано strager.


Обычно в C (за исключением компиляторов C99, как указывали другие) и C ++, если вы хотите выделить память в стеке, размер того, что вы хотите выделить, должен быть известен во время компиляции. Локальные переменные выделяются в стеке, поэтому массив, длина которого зависит от параметра функции во время выполнения, нарушает это правило. Клейн правильно указал, что использование «нового» оператора - один из способов решения этой проблемы:


char *a = new char [n];

«a» по-прежнему является локальной переменной, выделенной в стеке, но вместо того, чтобы быть целым массивом (который имеет переменную длину), это всего лишь указатель на массив (который всегда имеет одинаковый размер и, таким образом, известен во время компиляции). Массив выделяется в куче, которая обычно воспроизводит аналог стека - стек предназначен для вещей с размером, известным во время компиляции, а куча - для вещей с размером, не известным во время компиляции.


Было бы разумным использовать vector<> а не массив? Или, поскольку вы заменяете char * , std::string ? Они хорошо работают с настройкой времени выполнения, хотя могут быть и другие причины не использовать их.


Что вы нашли в нем одним из расширений компилятора Gnu для языка C ++. В этом случае Visual C ++ полностью корректен. Массивы в C ++ должны быть определены с размером, являющимся постоянным выражением времени компиляции.

Была добавлена ​​функция C в обновлении 1999 года на этот язык, называемый массивами переменной длины, где это является законным. Если вы можете найти компилятор C, который поддерживает C99, что непросто. Но эта функция не является частью стандартного C ++, но не будет добавлена ​​в следующее обновление к стандарту C ++.

В C ++ есть два решения. Первый - использовать std :: vector, второй - использовать оператор new [] :

char *a = new char [n];

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







declaration