Включение VLA (массивов переменной длины) в MS Visual C ++?

Как я могу включить использование VLA, массивов переменной длины, как определено в C99, в MS Visual C ++ или это вообще невозможно?

Да, я знаю, что стандарт C ++ основан на C89 и что VLA недоступны в стандарте C89 и, следовательно, недоступны в C ++, но MSVC ++ также должен быть компилятором C, поведение, которое можно включить с помощью / Параметр компилятора TC (Compile as C Code (/TC)). Но это, похоже, не включает VLA, и процесс компиляции завершается с теми же ошибками при сборке, что и C ++ (Compile as C++ Code (/TP)). Может быть, компилятор MSVC ++ C совместим только с C89, или мне что-то не хватает (какая-то специальная конструкция или прагма / определение)?

Пример кода:

#include <stdlib.h>

int main(int argc, char **argv)
{
  char pc[argc+5];

  /* do something useful with pc */

  return EXIT_SUCCESS;
}

Ошибки компиляции:

ошибка C2057: ожидаемое постоянное выражение

ошибка C2466: невозможно выделить массив постоянного размера 0

ошибка C2133: 'pc': неизвестный размер


person Shinnok    schedule 09.03.2011    source источник
comment
Пользователи C ++ должны использовать std::vector вместо VLA. Однако совет не помогает решить этот вопрос из-за требования C.   -  person jww    schedule 15.09.2018


Ответы (5)


MSVC не является компилятором C99 и не поддерживает массивы переменной длины.

На странице https://docs.microsoft.com/en-us/cpp/c-language/ansi-conformance Документировано, что MSVC соответствует C90.

person Anthony Williams    schedule 09.03.2011
comment
Более того, он, вероятно, никогда не будет: connect.microsoft.com/VisualStudio/feedback/details/333273/ Жаль. - person John Zwinck; 09.03.2011
comment
Тогда это улаживает спор. :-) Есть ли расширение Microsoft для языка, которое позволяет использовать VLA? У GCC есть один, что позволяет им работать с C90 и C ++, помимо соответствия C99. gcc.gnu.org/onlinedocs/gcc/Variable-Length.html - person Shinnok; 09.03.2011
comment
Я думаю, что ссылка, которую предоставил Джон, указывает на то, что ее нет и скоро не будет. - person Anthony Williams; 09.03.2011
comment
Эти отзывы относятся к 2008 году, но, вероятно, так обстоят дела и сегодня. Спасибо за ответы. - person Shinnok; 09.03.2011
comment
Нет поддержки VLA. MS предлагает вам использовать режим компилятора C ++ с std :: vector в качестве замены VLA. - person Bo Persson; 09.03.2011
comment
Просто добавлю, что да, начиная с MSVS 2015, MS будет поддерживать только функции C99, которые также требуются для C ++ 11. На этом все решено. - person Peter M; 29.06.2016
comment
Что в этом глупого, так это то, что тем из нас, кто на самом деле написал идентичные структуры данных, которые БЫСТРЕЕ, чем std :: vector, нужны VLA (которые используются ответственно) в наших реализациях. Ну что ж, вернемся к отказу от поддержки MSVC. Полагаю, их потеря. - person CodeMouse92; 08.03.2018

VLA гораздо удобнее писать, но вы можете добиться аналогичного поведения, используя alloca(), когда распределение динамической памяти std::vector недопустимо.

http://msdn.microsoft.com/en-us/library/x9sx5da1.aspx

Использование alloca() в вашем примере даст:

#include <stdlib.h>
#include <alloca.h>

int main(int argc, char **argv)
{
  char* pc = (char*) alloca(sizeof(char) * (argc+5));

  /* do something useful with pc */

  return EXIT_SUCCESS;
}
person Bowie Owens    schedule 13.08.2013
comment
И alloca, и его друг _alloca устарели в пользу _malloca в новых версиях msvc. И использовать эту функцию так утомительно, что лучше просто объявить массив постоянной длины и использовать его. - person Björn Lindqvist; 21.01.2018
comment
разве вам не нужно освобождать память, выделенную alloca? - person HaseeB Mir; 08.04.2018
comment
@HaSeeBMiR Нет. Поскольку память, выделенная функцией alloca (), находится в стеке, она автоматически освобождается при раскручивании стека. Подробности см. В документации к вашей версии. - person Bowie Owens; 10.04.2018
comment
@ BjörnLindqvist: Что вас раздражает в _malloca()? Явный вызов _freea() позволит легко заменить другие методы распределения, если возникнет такая необходимость, а возможность вызова _freea() в середине функции кажется гораздо более полезной, чем отсутствие каких-либо средств освобождения памяти до выхода из функции. - person supercat; 28.04.2018
comment
Основная причина использования alloca заключается в том, что память стека работает быстрее, чем память кучи. Но _malloca не гарантируется возврат памяти стека, что означает непредсказуемую производительность в трудных для отладки крайних случаях, когда стек почти заполнен. В этих сценариях вы не сможете отладить утечки памяти, которых не произошло бы в противном случае, если бы вы забыли освободить выделенную память. Никакие инструменты, такие как valgrind, не могут помочь, потому что в 99% случаев память берется из стека, поэтому утечки нет! Представьте себе отладку утечки памяти, которая возникает только на некоторых машинах, потому что у них меньший размер стека ... - person Björn Lindqvist; 28.04.2018

Я столкнулся с той же проблемой, это невозможно в MS Visual C ++ 2015, вместо этого вы можете использовать вектор, чтобы сделать почти то же самое, только разница заключается в незначительных накладных расходах на процедуру управления ресурсами кучи (новое / удаление).

Хотя VLA удобен, но выделять недетерминированный объем памяти из стека с риском переполнения стека, как правило, не является хорошей идеей.

person TingQian LI    schedule 01.03.2018

MSVC 2015 не поддерживает C99. Используйте эту логику, используя вместо этого динамическое распределение памяти.

#include <stdlib.h>

int main(int argc, char** argv)
{
    char* pc = (char*)malloc((argc + 5) * sizeof(char));

    /* do something useful with pc */
    
    free(pc);
    return EXIT_SUCCESS;
}
person Nawin K Sharma    schedule 03.07.2021

Чтобы создать массив переменной длины с помощью c ++, используя ваш пример, вы должны сделать что-то вроде следующего:

size_t size = argc + 5;
vector<char> pc(size);

Если вы хотите преобразовать его в std: string:

string buffer(pc.begin(), pc.end());
person Jahmic    schedule 14.05.2020
comment
Это помечено C. Ответы на другие языки программирования не по теме и бесполезны. - person Lundin; 14.05.2020