当尝试在Visual Studio中编译一些C代码时,我经常会遇到很多错误。出现此问题的原因是Visual Studio的C编译器仅支持旧版本的C.如何快速修复所有C代码以与Visual Studio编译器兼容?
例如,我正在尝试从http://libwebsockets.org/trac/libwebsockets编译websocket.c
及相关标头。我收到很多关于“非法使用此类型作为表达式”的错误,根据其他答案,这表明我需要将我的变量声明移动到每个块的开头。
答案 0 :(得分:5)
Visual Studio不提供对ANSI C的完全支持。如果您希望C代码足够可移植以使用Visual Studio进行编译,则可能必须以C89为目标或将其编译为C ++代码。第一个选项是不必要的限制,除非由于某种原因你真的真的喜欢'89标准C并且你讨厌后来标准的所有新功能。
第二个选项,编译为C ++,可以通过改变目标语言类型,在comment中提及 dialer 。您可以通过右键单击源文件,然后选择属性,导航到 C / C ++ - >来执行此操作。高级并将编译为选项更改为编译为C ++ 代码。
您也可以使用命令行上的/Tp <filename>
开关作为C ++ specify the source file type,或使用/TP
开关将所有内容编译为C ++。< / p>
如果您要链接到用C编写的库,则上述修复可能导致链接失败。这是因为,现在您将C文件编译为C ++,函数名称将为mangled。当编译器添加库并尝试将您调用的函数的名称与库导出的函数匹配时,它将失败,因为库导出的名称将不被损坏。
为了解决这个问题,C ++允许您指定使用“C”链接导出特定名称,这会告诉编译器名称没有被修改。这通常通过在函数声明前添加extern "C"
前缀,或将所有内容放在
extern "C" {
/* header contents here */
}
训练有素的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
如果您使用完善且编码良好的C库,标题可能包含与此类似的内容。如果没有,您可能需要自己完成(如果库是开源的,请将更改作为补丁提交!)
从2013年7月开始有一个MSDN blog post,宣布已经为Visual Studio 2013实现了大量的C99功能。部分原因似乎是某些部分提到了这些功能C ++标准,所以无论如何它们都是必需的。新功能包括新的math.h
功能,新的inttypes.h
类型等。有关完整列表,请参阅帖子。
earlier post给出了以下花絮:
此外,一些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编译器魔法)。