【问题标题】:Enabling VLAs (variable length arrays) in MS Visual C++?在 MS Visual C++ 中启用 VLA(可变长度数组)?
【发布时间】: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 的要求,该建议对这个问题没有帮助。

标签: c visual-c++ c99 c89 variable-length-array


【解决方案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。关于其他编程语言的答案是题外话和无益的。
      猜你喜欢
      • 1970-01-01
      • 2012-12-14
      • 1970-01-01
      • 2020-02-16
      • 2016-09-03
      • 2018-07-05
      • 2021-07-11
      • 2015-05-19
      • 1970-01-01
      相关资源
      最近更新 更多