ifdef win32 linux,使用预定义宏检测编译环境(操作系统、编译器类型、编译器版本)...

在编写跨平台的程序时,我们经常使用预定义宏来检测编译环境。虽然编译器的手册中有预处理宏的介绍,但是不够详细,而且还有很多宏没有介绍。于是,我编写了一个小程序,显示常见C/C++编译器的编译器的预定义宏。

一、心得

最直接的办法是逐个逐个的用#ifdef判断宏是否存在,然后再printf显示其内容。可是预定义宏有些是整数、有些是字符串,还有些是关键字不能直接用printf输出,用起来挺麻烦的。

在网上发现一种不错办法,出自《关于CPP的预定义宏:unix、linux、i386、i586,大家中过招吗?》4楼“太平绅士”——

点击(此处)折叠或打开

#include

#define PT_MAKE_STR(x) { #x, PT_MAKE_STR_ESC(x) }

#define PT_MAKE_STR_ESC(x) #x

typedef struct

{

const char *name;

const char *value;

} MACRO_T;

/* Compilers */

const MACRO_T g_compilers[ ] =

{

#ifdef __INTEL_COMPILER /* Interl C++ */

PT_MAKE_STR( __INTEL_COMPILER ),

#endif

#ifdef _MSC_VER /* Visual C++ */

PT_MAKE_STR( _MSC_VER ),

#endif

#ifdef __GNUC__ /* GCC */

PT_MAKE_STR( __GNUC__ ),

#endif

#ifdef __DMC__ /* DMC++ */

PT_MAKE_STR( __DMC__ ),

#endif

#ifdef __ARMCC_VERSION /* ARM C/C++ */

PT_MAKE_STR( __ARMCC_VERSION ),

#endif

};

/* Operation system */

const MACRO_T g_platforms[ ] =

{

#ifdef _WIN32 /* Windows 32 or Windows 64 */

PT_MAKE_STR( _WIN32 ),

#endif

#ifdef _WIN64 /* Windows 64 */

PT_MAKE_STR( _WIN64 ),

#endif

#ifdef __MINGW32__ /* Windows32 by mingw compiler */

PT_MAKE_STR( __MINGW32__ ),

#endif

#ifdef __CYGWIN__ /* Cygwin */

PT_MAKE_STR( __CYGWIN__ ),

#endif

#ifdef __linux__ /* linux */

PT_MAKE_STR( __linux__ ),

#endif

#ifdef __FreeBSD__ /* FreeBSD */

PT_MAKE_STR( __FreeBSD__ ),

#endif

#ifdef __NetBSD__ /* NetBSD */

PT_MAKE_STR( __NetBSD__ ),

#endif

#ifdef __OpenBSD__ /* OpenBSD */

PT_MAKE_STR( __OpenBSD__ ),

#endif

#ifdef __sun__ /* Sun OS */

PT_MAKE_STR( __sun__ ),

#endif

#ifdef __MaxOSX__ /* MAC OS X */

PT_MAKE_STR( __MaxOSX__ ),

#endif

#ifdef __unix__ /* unix */

PT_MAKE_STR( __unix__ ),

#endif

};

/* Other useful */

const MACRO_T g_others[ ] =

{

#ifdef __DATE__

PT_MAKE_STR( __DATE__ ),

#endif

#ifdef __TIME__

PT_MAKE_STR( __TIME__ ),

#endif

#ifdef _BSD_SOURCE

PT_MAKE_STR( _BSD_SOURCE ),

#endif

#ifdef _POSIX_SOURCE

PT_MAKE_STR( _POSIX_SOURCE ),

#endif

#ifdef _XOPEN_SOURCE

PT_MAKE_STR( _XOPEN_SOURCE ),

#endif

#ifdef _GNU_SOURCE

PT_MAKE_STR( _GNU_SOURCE ),

#endif

#ifdef __GNUC_MINOR__

PT_MAKE_STR( __GNUC_MINOR__ ),

#endif

#ifdef __VERSION__

PT_MAKE_STR( __VERSION__ ),

#endif

#ifdef __unix

PT_MAKE_STR( __unix ),

#endif

};

int main( int argc, char **argv )

{

int i;

printf( "/* Compiler definitions. */\n" );

for( i = 0; i < sizeof( g_compilers ) / sizeof( g_compilers[ 0 ] ); ++i )

{

printf( "#define %s %s\n", g_compilers[ i ].name, g_compilers[ i ].value );

}

printf( "\n" );

printf( "/* Platform definitions. */\n" );

for( i = 0; i < sizeof( g_platforms ) / sizeof( g_platforms[ 0 ] ); ++i )

{

printf( "#define %s %s\n", g_platforms[ i ].name, g_platforms[ i ].value );

}

printf( "\n" );

printf( "/* Other definitions. */\n" );

for( i = 0; i < sizeof( g_others ) / sizeof( g_others[ 0 ] ); ++i )

{

printf( "#define %s %s\n", g_others[ i ].name, g_others[ i ].value );

}

printf( "\n" );

return 0;

}

该方法巧妙的利用“#”运算将宏转成了字符串并填写数组,然后程序只需显示数组内容就行了。

我在该方法的基础上做了三点改进——

1. main函数中有很多相似的代码,区别仅仅是数组的不同。可以编写一个print_MACRO_T函数来显示MACRO_T数组,然后在main函数中对每一个数组调用该函数。

2. 当某个数组的宏均不存在时,编译器会报错。可以在数组的第一行填上该类别的描述信息,保证编译通过。另一个好处是精简了main函数中显示不同类别描述信息的代码。

3. 某些编译器不支持内容为空的宏(如BCB6)。这时只有手动#if做兼容性处理了。

二、全部代码

预定义宏的数据来自——C11标准、C++11标准,及VC、BCB、Intel、GCC这些编译器。

最初想删除重名的宏,后来考虑到需要对照各个编译器的手册,所以还是允许重名比较好。

全部代码——

点击(此处)折叠或打开

#include

#define PT_MAKE_STR(x) { #x, PT_MAKE_STR_ESC(x) }

#define PT_MAKE_STR_ESC(x) #x

typedef struct tagMACRO_T

{

const char *name;

const char *value;

} MACRO_T;

/* Compilers */

const MACRO_T g_compilers[] =

{

{"[Compiler]", ""},

#ifdef _MSC_VER /* Visual C++ */

PT_MAKE_STR( _MSC_VER ),

#endif

#ifdef __BORLANDC__

PT_MAKE_STR(__BORLANDC__),

#endif

#ifdef __INTEL_COMPILER /* Interl C++ */

PT_MAKE_STR( __INTEL_COMPILER ),

#endif

#ifdef __GNUC__ /* GCC */

PT_MAKE_STR( __GNUC__ ),

#endif

#ifdef __DMC__ /* DMC++ */

PT_MAKE_STR( __DMC__ ),

#endif

#ifdef __ARMCC_VERSION /* ARM C/C++ */

PT_MAKE_STR( __ARMCC_VERSION ),

#endif

#ifdef __APPLE_CC__ /* Apple's own GCC */

PT_MAKE_STR( __APPLE_CC__ ),

#endif

};

/* Operation system */

const MACRO_T g_platforms[] =

{

{"[Platform]", ""},

#ifdef __i386__

PT_MAKE_STR(__i386__),

#endif

#ifdef __x86_64__

PT_MAKE_STR(__x86_64__),

#endif

#ifdef __AMD64__

PT_MAKE_STR(__AMD64__),

#endif

#ifdef __amd64__

PT_MAKE_STR(__amd64__),

#endif

#ifdef __ia64__

PT_MAKE_STR(__ia64__),

#endif

#ifdef __alpha__

PT_MAKE_STR(__alpha__),

#endif

#ifdef __arm__

PT_MAKE_STR(__arm__),

#endif

#ifdef __sparc__

PT_MAKE_STR(__sparc__),

#endif

#ifdef __arch64__

PT_MAKE_STR(__arch64__),

#endif

#ifdef __powerpc__

PT_MAKE_STR(__powerpc__),

#endif

#ifdef __powerpc64__

PT_MAKE_STR(__powerpc64__),

#endif

#ifdef __ppc__

PT_MAKE_STR(__ppc__),

#endif

#ifdef __ppc64__

PT_MAKE_STR(__ppc64__),

#endif

#ifdef _WIN32 /* Windows 32 or Windows 64 */

PT_MAKE_STR( _WIN32 ),

#endif

#ifdef _WIN64 /* Windows 64 */

PT_MAKE_STR( _WIN64 ),

#endif

#ifdef __MINGW32__ /* Windows32 by mingw compiler */

PT_MAKE_STR( __MINGW32__ ),

#endif

#ifdef __CYGWIN__ /* Cygwin */

PT_MAKE_STR( __CYGWIN__ ),

#endif

#ifdef __linux__ /* linux */

PT_MAKE_STR( __linux__ ),

#endif

#ifdef __FreeBSD__ /* FreeBSD */

PT_MAKE_STR( __FreeBSD__ ),

#endif

#ifdef __NetBSD__ /* NetBSD */

PT_MAKE_STR( __NetBSD__ ),

#endif

#ifdef __OpenBSD__ /* OpenBSD */

PT_MAKE_STR( __OpenBSD__ ),

#endif

#ifdef __sun__ /* Sun OS */

PT_MAKE_STR( __sun__ ),

#endif

#ifdef __MaxOSX__ /* MAC OS X */

PT_MAKE_STR( __MaxOSX__ ),

#endif

#ifdef __unix__ /* unix */

PT_MAKE_STR( __unix__ ),

#endif

#ifdef __APPLE__

PT_MAKE_STR( __APPLE__ ),

#endif

#ifdef linux

PT_MAKE_STR( linux ),

#endif

#ifdef _LINUX

PT_MAKE_STR( _LINUX ),

#endif

#ifdef __USE_BSD

PT_MAKE_STR( __USE_BSD ),

#endif

};

/* Standard C. C11, C++11 */

const MACRO_T g_stdc[] =

{

/* [C11]: ISO/IEC 9899:2011 - Information technology -- Programming languages -- C. http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=57853 */

/* [C++11]: ISO/IEC 14882:2011 - Information technology -- Programming languages -- C++. http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=50372 */

{"[Standard C]", ""},

/* [C11] 6.10.8.1 Mandatory macros */

#ifdef __FILE__

PT_MAKE_STR(__FILE__),

#endif

#ifdef __LINE__

PT_MAKE_STR(__LINE__),

#endif

#ifdef __DATE__

PT_MAKE_STR(__DATE__),

#endif

#ifdef __TIME__

PT_MAKE_STR(__TIME__),

#endif

#ifdef __TIMESTAMP__

PT_MAKE_STR(__TIMESTAMP__),

#endif

#ifdef __STDC__

PT_MAKE_STR(__STDC__),

#endif

#ifdef __STDC_HOSTED__

PT_MAKE_STR(__STDC_HOSTED__),

#endif

#ifdef __STDC_VERSION__

PT_MAKE_STR(__STDC_VERSION__),

#endif

/* [C11] 6.10.8.2 Environment macros */

#ifdef __STDC_ISO_10646__

PT_MAKE_STR(__STDC_ISO_10646__),

#endif

#ifdef __STDC_MB_MIGHT_NEQ_WC__

PT_MAKE_STR(__STDC_MB_MIGHT_NEQ_WC__),

#endif

#ifdef __STDC_UTF_16__

PT_MAKE_STR(__STDC_UTF_16__),

#endif

#ifdef __STDC_UTF_32__

PT_MAKE_STR(__STDC_UTF_32__),

#endif

/* [C11] 6.10.8.3 Conditional feature macros */

#ifdef __STDC_ANALYZABLE__

PT_MAKE_STR(__STDC_ANALYZABLE__),

#endif

#ifdef __STDC_IEC_559__

PT_MAKE_STR(__STDC_IEC_559__),

#endif

#ifdef __STDC_IEC_559_COMPLEX__

PT_MAKE_STR(__STDC_IEC_559_COMPLEX__),

#endif

#ifdef __STDC_LIB_EXT1__

PT_MAKE_STR(__STDC_LIB_EXT1__),

#endif

#ifdef __STDC_NO_ATOMICS__

PT_MAKE_STR(__STDC_NO_ATOMICS__),

#endif

#ifdef __STDC_NO_COMPLEX__

PT_MAKE_STR(__STDC_NO_COMPLEX__),

#endif

#ifdef __STDC_NO_THREADS__

PT_MAKE_STR(__STDC_NO_THREADS__),

#endif

#ifdef __STDC_NO_VLA__

PT_MAKE_STR(__STDC_NO_VLA__),

#endif

/* [C++11] 16.8 Predefined macro names */

#ifdef __cplusplus

PT_MAKE_STR(__cplusplus),

#endif

#ifdef __STDCPP_STRICT_POINTER_SAFETY__

PT_MAKE_STR(__STDCPP_STRICT_POINTER_SAFETY__),

#endif

#ifdef __STDCPP_THREADS__

PT_MAKE_STR(__STDCPP_THREADS__),

#endif

#ifdef __OBJC__

PT_MAKE_STR(__OBJC__),

#endif

#ifdef __ASSEMBLER__

PT_MAKE_STR(__ASSEMBLER__),

#endif

#ifdef NDEBUG

PT_MAKE_STR(NDEBUG),

#endif

};

/* Microsoft Visual C++. VC++ 2012 */

const MACRO_T g_vc[] =

{

{"[Visual C++]", ""},

#ifdef _ATL_VER

PT_MAKE_STR(_ATL_VER),

#endif

#ifdef _CHAR_UNSIGNED

PT_MAKE_STR(_CHAR_UNSIGNED),

#endif

#ifdef __CLR_VER

PT_MAKE_STR(__CLR_VER),

#endif

#ifdef __cplusplus_cli

PT_MAKE_STR(__cplusplus_cli),

#endif

#ifdef __COUNTER__

PT_MAKE_STR(__COUNTER__),

#endif

#ifdef __cplusplus

PT_MAKE_STR(__cplusplus),

#endif

#ifdef _CPPRTTI

PT_MAKE_STR(_CPPRTTI),

#endif

#ifdef _CPPUNWIND

PT_MAKE_STR(_CPPUNWIND),

#endif

#ifdef _DEBUG

#if (defined(__BORLANDC__))

{"_DEBUG", "#"},

#else

PT_MAKE_STR(_DEBUG),

#endif

#endif

#ifdef _DLL

PT_MAKE_STR(_DLL),

#endif

#ifdef __FUNCDNAME__

PT_MAKE_STR(__FUNCDNAME__),

#endif

#ifdef __FUNCSIG__

PT_MAKE_STR(__FUNCSIG__),

#endif

#ifdef __FUNCTION__

PT_MAKE_STR

简单应用:

点击(此处)折叠或打开

#define VerifyVersion(majar, minor, plvl) (__GNUC__ > majar || (__GNUC__ == majar && __GNUC_MINOR__ > minor) \

|| (__GNUC__ == majar && __GNUC_MINOR__ == minor && __GNUC_PATCHLEVEL__ >= plvl))

printf("platform : ");

#ifdef __linux__

printf("linux");

#elif defined(_WIN32)

printf("windows(32)");

#elif defined(_WIN64)

printf("windows(64)");

#endif

printf("\n");

#ifdef __i386__

#endif

#ifdef __GNUC__

#if !VerifyVersion(4,7)

#error "Gcc Version is too low. (" __VERSION__ ")"

#endif

printf("GCC %s\n", __VERSION__);

#elif defined(_MSC_VER)

printf("Visual C++ %s\n"

#if _MSC_VER >= 1500

"2008"    //9.0

#elif _MSC_VER >= 1400

"2005"    //8.0

#elif _MSC_VER >= 1400

"2003"    //7.0

#elif _MSC_VER >= 1300

"6.0"    //6.0

#elif _MSC_VER >= 1200

"5.0"    //5.0

#elif _MSC_VER >= 1100

#endif

);

#endif

参考文献——

《ISO/IEC 9899:2011 - Information technology -- Programming languages -- C》. ISO/IEC, 2011.

《ISO/IEC 14882:2011 - Information technology -- Programming languages -- C++》. ISO/IEC, 2011.

《[VS2012] Predefined Macros》. Microsoft, 2012.

《[VS2012] 预定义的宏》. Microsoft, 2012.

《[BCB6] C++Builder Language Guide》中的《Predefined macros》. Borland, 2002.

《Intel? C++ Compiler XE 12.1 User and Reference Guides》(Windows版)中的《Additional Predefined Macros》. Intel, 2011.http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/2011Update/cpp/win/index.htm

《Intel? C++ Compiler XE 12.1 User and Reference Guides》(Linux版)中的《Additional Predefined Macros》. Intel, 2011.http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/2011Update/cpp/lin/index.htm

《[GCC] The C Preprocessor》中的《3.7.2 Common Predefined Macros》. GNU, 2011.

《关于CPP的预定义宏:unix、linux、i386、i586,大家中过招吗?》. 太平绅士, 2009-02-10.

《C\C++宏大全》. http://www.cnblogs.com/sevencat/archive/2004/06/10/14872.html

《Useful GCC Macros》. OneSadCookie, 2007-07-12. http://blog.onesadcookie.com/2007/07/useful-gcc-macros.html

《[笔记] Intel C++编译器的预定义宏(Windows版、Linux版)》. http://www.cnblogs.com/zyl910/archive/2012/07/06/intel_predefined_macros.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值