如何根据编译器类型使用#ifdef?GCC或VC++

26

我曾经使用#ifdef Win32来实现类似sprintf_s的安全调用,但现在我想使用MinGW构建项目,这种方法不再适用了。我需要使用#ifdef VC++或类似的方法。这可能吗?


2
顺便提一下,您可以使用 snprintf() 函数,它是一个标准函数,可以完成相同的任务。 - FatalError
@FatalError 在Visual C++中不支持,遗憾的是只有C89支持,并且snprintf在C89中并不保证存在。有类似的_snprintf,但我记得它没有被重命名为snprintf,因为它执行的操作略有不同。 - autistic
3个回答

57
#ifdef __clang__
/*code specific to clang compiler*/
#elif __GNUC__
/*code for GNU C compiler */
#elif _MSC_VER
/*usually has the version number in _MSC_VER*/
/*code specific to MSVC compiler*/
#elif __BORLANDC__
/*code specific to borland compilers*/
#elif __MINGW32__
/*code specific to mingw compilers*/
#endif

2
__GNUC__是一种语言方言,而不是编译器。大多数编译器(包括Clang和ICC)有时都会定义__GNUC__ - Quuxplusone
1
@Quuxplusone __GNUC__ 是一种语言方言,但你编写的代码通常是为编译器和人类而设计的。然而,如果你的意思是让我通过将 /* code for GNU C compiler */ 更改为 /* code in GNU C Dialect */ 来改进这个答案,那么你可以提交一个改进提案。 - Aniket Inge
只是指出,如果OP试图区分GCC和VC++与“某些其他编译器也支持GNU C”(例如ICC、Clang、Green Hills等),那么检查__GNUC__将是不够的。在这种情况下,这个问题/答案更适合他们的情况 - Quuxplusone
在macOS上,clang定义了gcc标志,因此您需要执行一些额外的逻辑,例如:#if GNUC #ifndef clang #pragma GCC diagnostic warning "-Wclass-memaccess" #endif #endif - Goblinhack
1
啊 - 我看到你把clang放在第一位,从而避免了clang启用__GNUC__的问题。 - Goblinhack

11
请参阅Visual C 预定义宏的“Microsoft-Specific Predefined Macros”表格。
您可以检查_MSC_VER

8

最好使用可移植符号。我知道有时这些符号可能没有定义,因此您可以查看Predef project以获取有关标准、编译器、库、操作系统和不可移植架构的预处理器宏的广泛列表。

但是,您在此问题中特别提到的函数已经作为Annex K.3,边界检查接口(库)的一部分包含在C11标准中。

K.3.1.1p2指出:

如果在源文件中适当的头文件首次被包含的地方,将__STDC_WANT_LIB_EXT1__定义为扩展到整数常量1的宏,则在其各自的头文件中声明或定义K.3及其子条款中声明和定义的函数、宏和类型。

因此,您应优先检查__STDC_WANT_LIB_EXT1__,仅在不存在时使用特定于编译器的符号。

1
不错,以前从没听说过这个链接,谢谢你的分享。 - Ron Burk

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