在MS Visual C++中启用VLAs(可变长度数组)?

33

我应该如何在MS Visual C++中启用VLAs(变长数组,C99中定义的),或者根本不可能实现?

我知道C++标准基于C89,因此VLAs在C89标准中不可用,因此在C++中也不可用。但是MSVC ++也应该是一个C编译器,可以使用/TC编译器参数(编译为C代码(/TC))来切换行为。 然而,这样做似乎并没有启用VLAs,并且在作为C++进行构建时会导致相同的错误(编译为C++代码(/TP))。也许MSVC++ C编译器仅符合C89标准,或者我缺少某些特殊结构或pragma/define。

示例代码:

#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' : 未知大小


C++用户应该使用std::vector而不是VLA。然而,由于C的要求,这个建议对这个问题没有帮助。 - jww
5个回答

32

6
很遗憾,不仅如此,它很可能永远都不会实现:http://connect.microsoft.com/VisualStudio/feedback/details/333273/request-for-c99-vla-in-visual-studio。非常遗憾。 - John Zwinck
那么争端就这样解决了。 :-) 是否有微软扩展语言的方法来实现可变长度数组?GCC 有一个,因此可以使它们符合 C90 和 C++,除了 C99。http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html - Shinnok
我认为约翰提供的链接表明目前没有,并且短期内也不会有。 - Anthony Williams
不支持可变长数组。微软建议您使用编译器的 C++ 模式,并使用 std::vector 作为可变长数组的替代品。 - Bo Persson
只是补充一下,是的,从 MSVS 2015 开始,微软只会支持 C99 特性,并且这些特性也被 C++11 所需要。此时此刻已经定下来了。 - Peter M
显示剩余2条评论

9

使用VLA非常方便,但当std::vector的动态内存分配受到限制时,您可以使用alloca()获得类似的行为。

http://msdn.microsoft.com/zh-cn/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;
}

6
在较新版本的MSVC中,alloca及其伙伴_alloca已被弃用,推荐使用_malloca。但是,该函数使用起来非常麻烦,最好只声明一个固定长度的数组并使用它。 - Björn Lindqvist
你不需要释放由alloca分配的内存吗? - Haseeb Mir
@HaSeeBMiR 不行。由alloca()分配的内存位于堆栈上,在堆栈展开时会自动回收。请查看您版本的文档以了解具体细节。 - Bowie Owens
@BjörnLindqvist:你对_malloca()有什么不爽的地方?显式调用_freea()将允许在需要时轻松替换其他分配方法,并且能够在函数中间调用_freea()似乎比没有释放存储的手段更有用,因为这样可以在函数退出之前释放存储。 - supercat
6
使用 alloca 的主要原因是栈内存比堆内存更快。但是 _malloca 不能保证返回栈内存,这意味着在栈几乎满时会出现难以调试的边缘情况下的不可预测性能问题。在这些情况下,你将得到无法调试的内存泄漏,而在忘记释放分配的内存时则不会发生这种情况。没有像 valgrind 这样的工具可以帮助解决问题,因为99%的时间内存是从栈中获取的,所以泄漏并不存在!想象一下在某些机器上仅发生在那些具有较小栈大小的内存泄漏的调试过程中...... - Björn Lindqvist

6

我遇到了同样的问题,但在MS Visual C++ 2015中不可能实现,相反你可以使用vector来做几乎相同的事情,唯一的区别是堆资源管理例程(new/delete)的开销可以忽略不计。

虽然可变长度数组很方便,但从堆栈分配不确定数量的内存存在着栈溢出的风险,通常不是一个好主意。


0

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;
}

-3
使用C++创建可变长度数组,可以像下面这样使用您的示例来实现:
size_t size = argc + 5;
vector<char> pc(size);

如果你想将它转换为std:string:

string buffer(pc.begin(), pc.end());

6
此内容标记为C语言。关于其他编程语言的答案是不相关和无用的。 - Lundin
+1 这个问题被标记为 visual-c++。在同样的情况下,它给了我一个避免在具有多个返回值的函数中使用“new char[size]”来创建VLA的想法... vector<char> vbuf(size); char *buf = & * vbuf.begin(); - Firstrock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接