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

Posted

技术标签:

【中文标题】在 MS Visual C++ 中启用 VLA(可变长度数组)?【英文标题】:Enabling VLAs (variable length arrays) in MS Visual C++? 【发布时间】:2011-07-11 22:33:18 【问题描述】:

如何启用 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,或者我遗漏了一些东西(一些特殊的构造或 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 的要求,该建议对这个问题没有帮助。 【参考方案1】:

MSVC 不是 C99 编译器,不支持变长数组。

在https://docs.microsoft.com/en-us/cpp/c-language/ansi-conformance,MSVC 被记录为符合 C90。

【讨论】:

不仅如此,它可能永远不会:connect.microsoft.com/VisualStudio/feedback/details/333273/… 太糟糕了。 这样就解决了争端。 :-) 启用 VLA 的语言是否有 Microsoft 扩展? GCC 有一个,因此除了符合 C99 标准外,它们还支持 C90 和 C++。 gcc.gnu.org/onlinedocs/gcc/Variable-Length.html 我认为 John 提供的链接表明没有,而且不会很快出现。 该反馈来自 2008 年,但今天可能也是如此。感谢您的回答。 不支持 VLA。 MS建议你使用编译器的C++模式,用std::vector代替VLA。【参考方案2】:

VLA 编写起来要简洁得多,但是当 std::vector 的动态内存分配令人望而却步时,您可以使用 alloca() 获得类似的行为。

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;

【讨论】:

alloca 和它的朋友 _alloca 在较新版本的 msvc 中都被 _malloca 弃用。而且该函数使用起来很烦人,最好只声明一个恒定长度的数组并使用它。 你不需要释放 alloca 分配的内存吗? @HaSeeBMiR 否。由于 alloca() 分配的内存在堆栈上,因此在堆栈展开时会自动回收。有关详细信息,请参阅您的版本的文档。 @BjörnLindqvist:您对_malloca() 有什么不满?显式调用_freea() 将允许在需要时轻松替换其他分配方法,并且能够在函数中间调用_freea() 似乎比在函数退出之前没有任何释放存储的方法有用得多。 使用alloca的主要原因是栈内存比堆内存快。但是_malloca 不能保证返回堆栈内存,这意味着在堆栈几乎已满时难以调试的边缘情况下的性能不可预测。在这些情况下,您将无法调试在忘记释放分配的内存时不会发生的内存泄漏。没有像 valgrind 这样的工具可以提供帮助,因为 99% 的时间内存都是从堆栈中取出的,所以不存在泄漏!想象一下调试一个只发生在某些机器上的 memleak,因为它们的堆栈大小更小......【参考方案3】:

我遇到了同样的问题,这在 MS Visual C++ 2015 中是不可能的,相反您可以使用向量来做几乎相同的事情,唯一的区别是堆资源管理例程(新建/删除)的可忽略的开销。

虽然 VLA 很方便,但是从堆栈中分配不确定数量的内存,有堆栈溢出的风险通常不是一个好主意。

【讨论】:

【参考方案4】:

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;

【讨论】:

【参考方案5】:

要使用 c++ 创建可变长度数组,使用您的示例,您可以执行以下操作:

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

如果你想把它转换成 std​​:string:

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

【讨论】:

这是标记为 C。关于其他编程语言的答案是题外话和无益的。

以上是关于在 MS Visual C++ 中启用 VLA(可变长度数组)?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 替代 C99 VLA(目标:保持性能)

在 C++ 中添加多行注释时如何在 Visual Studio 2010 中启用自动星号?

在 MS Visual C++ 中调试未处理异常的正确方法

在 Visual Studio 2012 中编译启用 CLR 的 C++ 项目时出现 C2248 错误

如何在 Visual C++ 2010 中从 C++0x 启用 nullptr?

发现凸缺陷?在 OpenCV 2.3 中,c++ 与 MS Visual Studio 2010