为什么C代码在Visual Studio中没有正确编译?

Chr*_*art 5 c visual-studio visual-studio-2012

当尝试在Visual Studio中编译一些C代码时,我经常会遇到很多错误.出现此问题的原因是Visual Studio的C编译器仅支持旧版本的C.如何快速修复所有C代码以与Visual Studio编译器兼容?

例如,我正在尝试编译websocket.c和关联的头文件 - 来自http://libwebsockets.org/trac/libwebsockets.我收到很多关于"非法使用此类型作为表达式"的错误,根据其他答案,这表明我需要将我的变量声明移动到每个块的开头.

Ant*_*ony 5

在Visual Studio中编译C的问题

Visual Studio不提供对ANSI C的完全支持.如果您希望C代码足够可移植以使用Visual Studio进行编译,则可能必须以C89为目标或将其编译为C++代码.第一种选择是不必要的限制,除非出于某种原因你真的喜欢'89标准C并且你讨厌后来标准的所有新功能.

编译为C++

第二个选项,编译为C++,可以通过改变目标语言类型来实现,正如拨号器在他的评论中提到的那样.您可以通过右键单击源文件,然后选择" 属性",导航到" C/C++" - >"高级"并将" 编译为"选项更改为" 编译为C++代码"来完成此操作.

您还可以使用命令行上的开关将源文件类型指定为C++ /Tp <filename>,或使用/TP开关将所有内容编译为C++.

链接问题

如果您链接到用C编写的库,则上述修复可能导致链接失败.这是因为,既然您正在将C文件编译为C++,那么函数名称将被破坏.当编译器添加库并尝试将您调用的函数的名称与库导出的函数匹配时,它将失败,因为库导出的名称不会被破坏.

为了解决这个问题,C++允许您指定使用"C"链接导出特定名称,这会告诉编译器名称不会被破坏.这通常通过在函数声明前加上前缀extern "C"或将所有内容放在一个块中来完成

extern "C" {
    /* header contents here */
}
Run Code Online (Sandbox Code Playgroud)

训练有素的C库开发人员知道这个问题,并将使用宏等技术来对抗它.一种常见的技术是检测用户何时编译为C++,并在头文件的声明块的开头和结尾放置类似于这些的宏:

#if defined (__cplusplus)
#define BEGIN_EXTERN_C extern "C" {
#define END_EXTERN_C }
#else
#define BEGIN_EXTERN_C 
#define END_EXTERN_C 
#endif
Run Code Online (Sandbox Code Playgroud)

如果您使用的是完善且编码良好的C库,则标题可能包含与此类似的内容.如果没有,您可能需要自己完成(如果库是开源的,请将更改作为补丁提交!)

Visual Studio中C的未来

从2013年7月开始有一篇MSDN博客文章,其中宣布为Visual Studio 2013实现了大量C99功能.部分原因似乎是某些C++标准部分提到了这些功能,所以无论如何都会被要求.新功能包括新math.h功能,新功能inttypes.h等.有关完整列表,请参阅帖子.

一个早期的岗位提供了以下花絮:

此外,一些C99核心语言功能将在2013 RTM中实施:

  • C99 _Bool
  • C99复合文字
  • C99指定的初始化器
  • C99变量声明

请注意,缺少某些功能,包括:

  • 缺少tgmath.h标头.此标头需要C编译器支持.
    • 请注意,添加了ctgmath标头 - 这是可能的,因为该标头不需要tgmath.h标头 - 仅ccomplex和cmath标头.
  • 缺少uchar.h标头.这是来自C Unicode TR.
  • 目前还不支持printf系列中的几个格式说明符.
  • stdio.h和wchar.h中缺少snprintf和snwprintf函数.

虽然你可以期待它们:

我们不讨厌snprintf()(恰恰相反),我们只是错过了它并且没时间了.

请注意,与标准库无关的其他语言功能仍然不可用.

看起来标准C将来会获得更多支持,尽管可能只是因为支持C++ 11和C++ 14需要实现更多现代功能.

<tgmath.h> 它的相关编译器魔法是特殊的,我不知道我们对它们的计划(正如Pat的帖子解释的那样,C++有重载/模板,不需要C编译器魔法).

  • 这个答案中的所有内容都是正确的,我只是要留下一个一般性说明,将 C 程序编译为 C++ 确实是一个坏主意。两种语言之间有许多细微的区别:`struct` 的含义、隐式指针强制转换、`bool` 类型、`NULL` 的含义等等。就像我说的,编译为 C++ 可能*仍然*你最好的选择,但它不是一个好选择。微软在这里真的把 C 开发人员搞砸了。他们声称这些还不够重要。如果您不同意,请给他们发电子邮件。 (2认同)