[转载] http://www.cnblogs.com/zyl910/archive/2012/08/02/printmacro.html

作者:zyl910

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

一、心得

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

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


点击(此处)折叠或打开

  1. #include <stdio.h>


  2. #define PT_MAKE_STR(x) { #x, PT_MAKE_STR_ESC(x) }
  3. #define PT_MAKE_STR_ESC(x) #x


  4. typedef struct
  5. {
  6.     const char *name;
  7.     const char *value;
  8. } MACRO_T;


  9. /* Compilers */
  10. const MACRO_T g_compilers[ ] =
  11. {
  12. #ifdef __INTEL_COMPILER /* Interl C++ */
  13.     PT_MAKE_STR( __INTEL_COMPILER ),
  14. #endif
  15.         
  16. #ifdef _MSC_VER /* Visual C++ */
  17.         PT_MAKE_STR( _MSC_VER ),
  18. #endif
  19.         
  20. #ifdef __GNUC__ /* GCC */
  21.         PT_MAKE_STR( __GNUC__ ),
  22. #endif
  23.         
  24. #ifdef __DMC__ /* DMC++ */
  25.         PT_MAKE_STR( __DMC__ ),
  26. #endif
  27.         
  28. #ifdef __ARMCC_VERSION /* ARM C/C++ */
  29.         PT_MAKE_STR( __ARMCC_VERSION ),
  30. #endif
  31. };


  32. /* Operation system */
  33. const MACRO_T g_platforms[ ] =
  34. {
  35. #ifdef _WIN32 /* Windows 32 or Windows 64 */
  36.     PT_MAKE_STR( _WIN32 ),
  37. #endif
  38.         
  39. #ifdef _WIN64 /* Windows 64 */
  40.         PT_MAKE_STR( _WIN64 ),
  41. #endif
  42.         
  43. #ifdef __MINGW32__ /* Windows32 by mingw compiler */
  44.         PT_MAKE_STR( __MINGW32__ ),
  45. #endif
  46.         
  47. #ifdef __CYGWIN__ /* Cygwin */
  48.         PT_MAKE_STR( __CYGWIN__ ),
  49. #endif
  50.         
  51. #ifdef __linux__ /* linux */
  52.         PT_MAKE_STR( __linux__ ),
  53. #endif
  54.         
  55. #ifdef __FreeBSD__ /* FreeBSD */
  56.         PT_MAKE_STR( __FreeBSD__ ),
  57. #endif
  58.         
  59. #ifdef __NetBSD__ /* NetBSD */
  60.         PT_MAKE_STR( __NetBSD__ ),
  61. #endif
  62.         
  63. #ifdef __OpenBSD__ /* OpenBSD */
  64.         PT_MAKE_STR( __OpenBSD__ ),
  65. #endif
  66.         
  67. #ifdef __sun__ /* Sun OS */
  68.         PT_MAKE_STR( __sun__ ),
  69. #endif
  70.         
  71. #ifdef __MaxOSX__ /* MAC OS X */
  72.         PT_MAKE_STR( __MaxOSX__ ),
  73. #endif
  74.         
  75. #ifdef __unix__ /* unix */
  76.         PT_MAKE_STR( __unix__ ),
  77. #endif
  78. };


  79. /* Other useful */
  80. const MACRO_T g_others[ ] =
  81. {
  82. #ifdef __DATE__
  83.     PT_MAKE_STR( __DATE__ ),
  84. #endif
  85.         
  86. #ifdef __TIME__
  87.         PT_MAKE_STR( __TIME__ ),
  88. #endif
  89.         
  90. #ifdef _BSD_SOURCE
  91.         PT_MAKE_STR( _BSD_SOURCE ),
  92. #endif
  93.         
  94. #ifdef _POSIX_SOURCE
  95.         PT_MAKE_STR( _POSIX_SOURCE ),
  96. #endif
  97.         
  98. #ifdef _XOPEN_SOURCE
  99.         PT_MAKE_STR( _XOPEN_SOURCE ),
  100. #endif
  101.         
  102. #ifdef _GNU_SOURCE
  103.         PT_MAKE_STR( _GNU_SOURCE ),
  104. #endif
  105.         
  106. #ifdef __GNUC_MINOR__
  107.         PT_MAKE_STR( __GNUC_MINOR__ ),
  108. #endif
  109.         
  110. #ifdef __VERSION__
  111.         PT_MAKE_STR( __VERSION__ ),
  112. #endif
  113.         
  114. #ifdef __unix
  115.         PT_MAKE_STR( __unix ),
  116. #endif
  117. };



  118. int main( int argc, char **argv )
  119. {
  120.     int i;
  121.     
  122.     printf( "/* Compiler definitions. */\n" );
  123.     for( i = 0; i < sizeof( g_compilers ) / sizeof( g_compilers[ 0 ] ); ++i )
  124.     {
  125.         printf( "#define %s %s\n", g_compilers[ i ].name, g_compilers[ i ].value );
  126.     }
  127.     printf( "\n" );
  128.     
  129.     printf( "/* Platform definitions. */\n" );
  130.     for( i = 0; i < sizeof( g_platforms ) / sizeof( g_platforms[ 0 ] ); ++i )
  131.     {
  132.         printf( "#define %s %s\n", g_platforms[ i ].name, g_platforms[ i ].value );
  133.     }
  134.     printf( "\n" );
  135.     
  136.     printf( "/* Other definitions. */\n" );
  137.     for( i = 0; i < sizeof( g_others ) / sizeof( g_others[ 0 ] ); ++i )
  138.     {
  139.         printf( "#define %s %s\n", g_others[ i ].name, g_others[ i ].value );
  140.     }
  141.     printf( "\n" );
  142.     
  143.     return 0;
  144. }


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

  我在该方法的基础上做了三点改进——
1. main函数中有很多相似的代码,区别仅仅是数组的不同。可以编写一个print_MACRO_T函数来显示MACRO_T数组,然后在main函数中对每一个数组调用该函数。
2. 当某个数组的宏均不存在时,编译器会报错。可以在数组的第一行填上该类别的描述信息,保证编译通过。另一个好处是精简了main函数中显示不同类别描述信息的代码。
3. 某些编译器不支持内容为空的宏(如BCB6)。这时只有手动#if做兼容性处理了。


二、全部代码

  预定义宏的数据来自——C11标准、C++11标准,及VC、BCB、Intel、GCC这些编译器。
  最初想删除重名的宏,后来考虑到需要对照各个编译器的手册,所以还是允许重名比较好。

  全部代码——


点击(此处)折叠或打开

  1. #include <stdio.h>


  2. #define PT_MAKE_STR(x) { #x, PT_MAKE_STR_ESC(x) }
  3. #define PT_MAKE_STR_ESC(x) #x


  4. typedef struct tagMACRO_T
  5. {
  6.     const char *name;
  7.     const char *value;
  8. } MACRO_T;

  9. /* Compilers */
  10. const MACRO_T g_compilers[] =
  11. {
  12.     {"[Compiler]", ""},
  13.         
  14. #ifdef _MSC_VER /* Visual C++ */
  15.     PT_MAKE_STR( _MSC_VER ),
  16. #endif
  17.     
  18. #ifdef __BORLANDC__
  19.     PT_MAKE_STR(__BORLANDC__),
  20. #endif
  21.     
  22. #ifdef __INTEL_COMPILER /* Interl C++ */
  23.     PT_MAKE_STR( __INTEL_COMPILER ),
  24. #endif
  25.     
  26. #ifdef __GNUC__ /* GCC */
  27.     PT_MAKE_STR( __GNUC__ ),
  28. #endif
  29.     
  30. #ifdef __DMC__ /* DMC++ */
  31.     PT_MAKE_STR( __DMC__ ),
  32. #endif
  33.     
  34. #ifdef __ARMCC_VERSION /* ARM C/C++ */
  35.     PT_MAKE_STR( __ARMCC_VERSION ),
  36. #endif
  37.     
  38. #ifdef __APPLE_CC__ /* Apple's own GCC */
  39.     PT_MAKE_STR( __APPLE_CC__ ),
  40. #endif
  41. };

  42. /* Operation system */
  43. const MACRO_T g_platforms[] =
  44. {
  45.     {"[Platform]", ""},
  46.         
  47. #ifdef __i386__
  48.     PT_MAKE_STR(__i386__),
  49. #endif
  50.     
  51. #ifdef __x86_64__
  52.     PT_MAKE_STR(__x86_64__),
  53. #endif
  54.     
  55. #ifdef __AMD64__
  56.     PT_MAKE_STR(__AMD64__),
  57. #endif
  58.     
  59. #ifdef __amd64__
  60.     PT_MAKE_STR(__amd64__),
  61. #endif
  62.     
  63. #ifdef __ia64__
  64.     PT_MAKE_STR(__ia64__),
  65. #endif
  66.     
  67. #ifdef __alpha__
  68.     PT_MAKE_STR(__alpha__),
  69. #endif
  70.     
  71. #ifdef __arm__
  72.     PT_MAKE_STR(__arm__),
  73. #endif
  74.     
  75. #ifdef __sparc__
  76.     PT_MAKE_STR(__sparc__),
  77. #endif
  78.     
  79. #ifdef __arch64__
  80.     PT_MAKE_STR(__arch64__),
  81. #endif
  82.     
  83. #ifdef __powerpc__
  84.     PT_MAKE_STR(__powerpc__),
  85. #endif
  86.     
  87. #ifdef __powerpc64__
  88.     PT_MAKE_STR(__powerpc64__),
  89. #endif
  90.     
  91. #ifdef __ppc__
  92.     PT_MAKE_STR(__ppc__),
  93. #endif
  94.     
  95. #ifdef __ppc64__
  96.     PT_MAKE_STR(__ppc64__),
  97. #endif
  98.     
  99. #ifdef _WIN32 /* Windows 32 or Windows 64 */
  100.     PT_MAKE_STR( _WIN32 ),
  101. #endif
  102.     
  103. #ifdef _WIN64 /* Windows 64 */
  104.     PT_MAKE_STR( _WIN64 ),
  105. #endif
  106.     
  107. #ifdef __MINGW32__ /* Windows32 by mingw compiler */
  108.     PT_MAKE_STR( __MINGW32__ ),
  109. #endif
  110.     
  111. #ifdef __CYGWIN__ /* Cygwin */
  112.     PT_MAKE_STR( __CYGWIN__ ),
  113. #endif
  114.     
  115. #ifdef __linux__ /* linux */
  116.     PT_MAKE_STR( __linux__ ),
  117. #endif
  118.     
  119. #ifdef __FreeBSD__ /* FreeBSD */
  120.     PT_MAKE_STR( __FreeBSD__ ),
  121. #endif
  122.     
  123. #ifdef __NetBSD__ /* NetBSD */
  124.     PT_MAKE_STR( __NetBSD__ ),
  125. #endif
  126.     
  127. #ifdef __OpenBSD__ /* OpenBSD */
  128.     PT_MAKE_STR( __OpenBSD__ ),
  129. #endif
  130.     
  131. #ifdef __sun__ /* Sun OS */
  132.     PT_MAKE_STR( __sun__ ),
  133. #endif
  134.     
  135. #ifdef __MaxOSX__ /* MAC OS X */
  136.     PT_MAKE_STR( __MaxOSX__ ),
  137. #endif
  138.     
  139. #ifdef __unix__ /* unix */
  140.     PT_MAKE_STR( __unix__ ),
  141. #endif
  142.         
  143.         ////////////////////////////////////////
  144. #ifdef __APPLE__
  145.     PT_MAKE_STR( __APPLE__ ),
  146. #endif
  147.     
  148. #ifdef linux
  149.     PT_MAKE_STR( linux ),
  150. #endif
  151.     
  152. #ifdef _LINUX
  153.     PT_MAKE_STR( _LINUX ),
  154. #endif
  155.     
  156. #ifdef __USE_BSD
  157.     PT_MAKE_STR( __USE_BSD ),
  158. #endif
  159.         
  160. };

  161. /* Standard C. C11, C++11 */
  162. const MACRO_T g_stdc[] =
  163. {
  164.     /* [C11]: ISO/IEC 9899:2011 - Information technology -- Programming languages -- C. http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=57853 */
  165.     /* [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 */
  166.     {"[Standard C]", ""},
  167.         
  168.         /* [C11] 6.10.8.1 Mandatory macros */
  169. #ifdef __FILE__
  170.     PT_MAKE_STR(__FILE__),
  171. #endif
  172.     
  173. #ifdef __LINE__
  174.     PT_MAKE_STR(__LINE__),
  175. #endif
  176.     
  177. #ifdef __DATE__
  178.     PT_MAKE_STR(__DATE__),
  179. #endif
  180.     
  181. #ifdef __TIME__
  182.     PT_MAKE_STR(__TIME__),
  183. #endif
  184.     
  185. #ifdef __TIMESTAMP__
  186.     PT_MAKE_STR(__TIMESTAMP__),
  187. #endif
  188.     
  189. #ifdef __STDC__
  190.     PT_MAKE_STR(__STDC__),
  191. #endif
  192.     
  193. #ifdef __STDC_HOSTED__
  194.     PT_MAKE_STR(__STDC_HOSTED__),
  195. #endif
  196.     
  197. #ifdef __STDC_VERSION__
  198.     PT_MAKE_STR(__STDC_VERSION__),
  199. #endif
  200.     
  201.     /* [C11] 6.10.8.2 Environment macros */
  202. #ifdef __STDC_ISO_10646__
  203.     PT_MAKE_STR(__STDC_ISO_10646__),
  204. #endif
  205.         
  206. #ifdef __STDC_MB_MIGHT_NEQ_WC__
  207.     PT_MAKE_STR(__STDC_MB_MIGHT_NEQ_WC__),
  208. #endif
  209.     
  210. #ifdef __STDC_UTF_16__
  211.     PT_MAKE_STR(__STDC_UTF_16__),
  212. #endif
  213.     
  214. #ifdef __STDC_UTF_32__
  215.     PT_MAKE_STR(__STDC_UTF_32__),
  216. #endif
  217.     
  218.     /* [C11] 6.10.8.3 Conditional feature macros */
  219. #ifdef __STDC_ANALYZABLE__
  220.     PT_MAKE_STR(__STDC_ANALYZABLE__),
  221. #endif
  222.     
  223. #ifdef __STDC_IEC_559__
  224.     PT_MAKE_STR(__STDC_IEC_559__),
  225. #endif
  226.     
  227. #ifdef __STDC_IEC_559_COMPLEX__
  228.     PT_MAKE_STR(__STDC_IEC_559_COMPLEX__),
  229. #endif
  230.     
  231. #ifdef __STDC_LIB_EXT1__
  232.     PT_MAKE_STR(__STDC_LIB_EXT1__),
  233. #endif
  234.     
  235. #ifdef __STDC_NO_ATOMICS__
  236.     PT_MAKE_STR(__STDC_NO_ATOMICS__),
  237. #endif
  238.     
  239. #ifdef __STDC_NO_COMPLEX__
  240.     PT_MAKE_STR(__STDC_NO_COMPLEX__),
  241. #endif
  242.     
  243. #ifdef __STDC_NO_THREADS__
  244.     PT_MAKE_STR(__STDC_NO_THREADS__),
  245. #endif
  246.     
  247. #ifdef __STDC_NO_VLA__
  248.     PT_MAKE_STR(__STDC_NO_VLA__),
  249. #endif
  250.     
  251.     /* [C++11] 16.8 Predefined macro names */
  252. #ifdef __cplusplus
  253.     PT_MAKE_STR(__cplusplus),
  254. #endif
  255.     
  256. #ifdef __STDCPP_STRICT_POINTER_SAFETY__
  257.     PT_MAKE_STR(__STDCPP_STRICT_POINTER_SAFETY__),
  258. #endif
  259.     
  260. #ifdef __STDCPP_THREADS__
  261.     PT_MAKE_STR(__STDCPP_THREADS__),
  262. #endif
  263.     
  264.     ////////////////////////////////////////
  265. #ifdef __OBJC__
  266.     PT_MAKE_STR(__OBJC__),
  267. #endif
  268.     
  269. #ifdef __ASSEMBLER__
  270.     PT_MAKE_STR(__ASSEMBLER__),
  271. #endif
  272.     
  273. #ifdef NDEBUG
  274.     PT_MAKE_STR(NDEBUG),
  275. #endif
  276. };

  277. /* Microsoft Visual C++. VC++ 2012 */
  278. const MACRO_T g_vc[] =
  279. {
  280.     {"[Visual C++]", ""},
  281.         
  282. #ifdef _ATL_VER
  283.     PT_MAKE_STR(_ATL_VER),
  284. #endif
  285.     
  286. #ifdef _CHAR_UNSIGNED
  287.     PT_MAKE_STR(_CHAR_UNSIGNED),
  288. #endif
  289.     
  290. #ifdef __CLR_VER
  291.     PT_MAKE_STR(__CLR_VER),
  292. #endif
  293.     
  294. #ifdef __cplusplus_cli
  295.     PT_MAKE_STR(__cplusplus_cli),
  296. #endif
  297.     
  298. #ifdef __COUNTER__
  299.     PT_MAKE_STR(__COUNTER__),
  300. #endif
  301.     
  302. #ifdef __cplusplus
  303.     PT_MAKE_STR(__cplusplus),
  304. #endif
  305.     
  306. #ifdef _CPPRTTI
  307.     PT_MAKE_STR(_CPPRTTI),
  308. #endif
  309.     
  310. #ifdef _CPPUNWIND
  311.     PT_MAKE_STR(_CPPUNWIND),
  312. #endif
  313.         
  314. #ifdef _DEBUG
  315. #if (defined(__BORLANDC__))
  316.     {"_DEBUG", "#"},
  317. #else
  318.     PT_MAKE_STR(_DEBUG),
  319. #endif
  320. #endif
  321.     
  322. #ifdef _DLL
  323.     PT_MAKE_STR(_DLL),
  324. #endif
  325.     
  326. #ifdef __FUNCDNAME__
  327.     PT_MAKE_STR(__FUNCDNAME__),
  328. #endif
  329.     
  330. #ifdef __FUNCSIG__
  331.     PT_MAKE_STR(__FUNCSIG__),
  332. #endif
  333.     
  334. #ifdef __FUNCTION__
  335.     PT_MAKE_STR


简单应用:

点击(此处)折叠或打开

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

  3. printf("platform : ");
  4. #ifdef __linux__
  5. printf("linux");
  6. #elif defined(_WIN32)
  7. printf("windows(32)");
  8. #elif defined(_WIN64)
  9. printf("windows(64)");
  10. #endif
  11. printf("\n");

  12. #ifdef __i386__
  13. #endif

  14. #ifdef __GNUC__
  15. #if !VerifyVersion(4,7)
  16. #error "Gcc Version is too low. (" __VERSION__ ")"
  17. #endif
  18. printf("GCC %s\n", __VERSION__);
  19. #elif defined(_MSC_VER)
  20. printf("Visual C++ %s\n"
  21. #if _MSC_VER >= 1500
  22.         "2008"    //9.0
  23. #elif _MSC_VER >= 1400
  24.         "2005"    //8.0
  25. #elif _MSC_VER >= 1400
  26.         "2003"    //7.0
  27. #elif _MSC_VER >= 1300
  28.         "6.0"    //6.0
  29. #elif _MSC_VER >= 1200
  30.         "5.0"    //5.0
  31. #elif _MSC_VER >= 1100
  32. #endif
  33.     );
  34. #endif

参考文献——
《ISO/IEC 9899:2011 - Information technology -- Programming languages -- C》. ISO/IEC, 2011.http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=57853
《ISO/IEC 14882:2011 - Information technology -- Programming languages -- C++》. ISO/IEC, 2011.http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=50372
《[VS2012] Predefined Macros》. Microsoft, 2012. http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.110).aspx
《[VS2012] 预定义的宏》. Microsoft, 2012. http://msdn.microsoft.com/zh-cn/library/b0084kay(v=vs.110).aspx
《[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. http://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html
《关于CPP的预定义宏:unix、linux、i386、i586,大家中过招吗?》. 太平绅士, 2009-02-10. http://bbs.chinaunix.net/thread-1366571-1-1.html
《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


源码下载—— 
http://files.cnblogs.com/zyl910/printmacro.rar

11-08 10:45