免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8576 | 回复: 16
打印 上一主题 下一主题

关于CPP的预定义宏:unix、linux、i386、i586,大家中过招吗? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-10 13:47 |只看该作者 |倒序浏览
前段时间碰到一个奇怪的编译问题,编译器总是报错:“parse error before 1”,后来使用一点点删除代码的方法,发现问题所在:我的程序中使用了“unix”作为标识符,但是在linux平台中unix是cpp的预定义宏,所以:

  1. class unix {
  2. }

  3. class linux:unix {
  4. }
复制代码

就会被处理成:

  1. class 1 {
  2. }

  3. class 1:1 {
  4. }
复制代码

我就感到奇怪了,unix、linux应该是个用户有可能用到的标识符吧,至少得加上__前缀(像__cpluscplus)那样保护下吧,把常见的标识符给预定义了,出了错真急死人,不解中....

这个例子,大家可以在自己的平台中测一下:

  1. int unix;
  2. int linux;
  3. int i386;  // 如果产生的是386代码,那么i386被预定义
  4. int i586;  // 如果产生的是586代码,那么i586被预定义

  5. int main()
  6. {
  7.      return 0;
  8. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2009-02-10 14:15 |只看该作者
似乎是几个define吧??

论坛徽章:
0
3 [报告]
发表于 2009-02-10 14:17 |只看该作者
楼主仔细回忆一下看过的代码

有没有看到过类似这样的

# ifdef unix

...


#endif //unix


#ifndef i386
...
#endif //i386

论坛徽章:
0
4 [报告]
发表于 2009-02-10 14:34 |只看该作者
贴一点测试代码

  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. #ifdef _MSC_VER                        /* Visual C++ */
  16.         PT_MAKE_STR( _MSC_VER ),
  17. #endif

  18. #ifdef __GNUC__                        /* GCC */
  19.         PT_MAKE_STR( __GNUC__ ),
  20. #endif

  21. #ifdef __DMC__                        /* DMC++ */
  22.         PT_MAKE_STR( __DMC__ ),
  23. #endif

  24. #ifdef __ARMCC_VERSION        /* ARM C/C++ */
  25.         PT_MAKE_STR( __ARMCC_VERSION ),
  26. #endif
  27. };


  28. /* Operation system */
  29. const MACRO_T g_platforms[ ] =
  30. {
  31. #ifdef _WIN32                        /* Windows 32 or Windows 64 */
  32.         PT_MAKE_STR( _WIN32 ),
  33. #endif

  34. #ifdef _WIN64                        /* Windows 64 */
  35.         PT_MAKE_STR( _WIN64 ),
  36. #endif

  37. #ifdef __MINGW32__                /* Windows32 by mingw compiler */
  38.         PT_MAKE_STR( __MINGW32__ ),
  39. #endif

  40. #ifdef __CYGWIN__                /* Cygwin */
  41.         PT_MAKE_STR( __CYGWIN__ ),
  42. #endif

  43. #ifdef __linux__                /* linux */
  44.         PT_MAKE_STR( __linux__ ),
  45. #endif

  46. #ifdef __FreeBSD__                /* FreeBSD */
  47.         PT_MAKE_STR( __FreeBSD__ ),
  48. #endif

  49. #ifdef __NetBSD__                /* NetBSD */
  50.         PT_MAKE_STR( __NetBSD__ ),
  51. #endif

  52. #ifdef __OpenBSD__                /* OpenBSD */
  53.         PT_MAKE_STR( __OpenBSD__ ),
  54. #endif

  55. #ifdef __sun__                /* Sun OS */
  56.         PT_MAKE_STR( __sun__ ),
  57. #endif

  58. #ifdef __MaxOSX__                /* MAC OS X */
  59.         PT_MAKE_STR( __MaxOSX__ ),
  60. #endif

  61. #ifdef __unix__                        /* unix */
  62.         PT_MAKE_STR( __unix__ ),
  63. #endif       
  64. };


  65. /* Other useful */
  66. const MACRO_T g_others[ ] =
  67. {
  68. #ifdef __DATE__
  69.         PT_MAKE_STR( __DATE__ ),
  70. #endif

  71. #ifdef __TIME__
  72.         PT_MAKE_STR( __TIME__ ),
  73. #endif

  74. #ifdef _BSD_SOURCE
  75.         PT_MAKE_STR( _BSD_SOURCE ),
  76. #endif

  77. #ifdef _POSIX_SOURCE
  78.         PT_MAKE_STR( _POSIX_SOURCE ),
  79. #endif

  80. #ifdef _XOPEN_SOURCE
  81.         PT_MAKE_STR( _XOPEN_SOURCE ),
  82. #endif

  83. #ifdef _GNU_SOURCE
  84.         PT_MAKE_STR( _GNU_SOURCE ),
  85. #endif

  86. #ifdef __GNUC_MINOR__
  87.         PT_MAKE_STR( __GNUC_MINOR__ ),
  88. #endif

  89. #ifdef __VERSION__
  90.         PT_MAKE_STR( __VERSION__ ),
  91. #endif

  92. #ifdef __unix
  93.         PT_MAKE_STR( __unix ),
  94. #endif
  95. };



  96. int main( int argc, char **argv )
  97. {
  98.         int i;

  99.         printf( "/* Compiler definitions. */\n" );
  100.         for( i = 0; i < sizeof( g_compilers ) / sizeof( g_compilers[ 0 ] ); ++i )
  101.         {
  102.                 printf( "#define %s %s\n", g_compilers[ i ].name, g_compilers[ i ].value );
  103.         }
  104.         printf( "\n" );

  105.         printf( "/* Platform definitions. */\n" );
  106.         for( i = 0; i < sizeof( g_platforms ) / sizeof( g_platforms[ 0 ] ); ++i )
  107.         {
  108.                 printf( "#define %s %s\n", g_platforms[ i ].name, g_platforms[ i ].value );
  109.         }
  110.         printf( "\n" );

  111.         printf( "/* Other definitions. */\n" );
  112.         for( i = 0; i < sizeof( g_others ) / sizeof( g_others[ 0 ] ); ++i )
  113.         {
  114.                 printf( "#define %s %s\n", g_others[ i ].name, g_others[ i ].value );
  115.         }
  116.         printf( "\n" );

  117.         return 0;
  118. }



复制代码

论坛徽章:
0
5 [报告]
发表于 2009-02-10 15:12 |只看该作者
原帖由 net_robber 于 2009-2-10 14:17 发表
楼主仔细回忆一下看过的代码

有没有看到过类似这样的

# ifdef unix

...


#endif //unix


#ifndef i386
...
#endif //i386

没有啊,我的测试例子就是下面这个简单的程序

  1. int unix;
  2. int linux;
  3. int i386;
  4. int i586;

  5. int main()
  6. {
  7.      return 0;
  8. }
复制代码

在FC 5和Cygwin下编译出错,你不妨也编译一把试试看。

论坛徽章:
0
6 [报告]
发表于 2009-02-10 15:18 |只看该作者
原帖由 太平绅士 于 2009-2-10 14:34 发表
贴一点测试代码

...

__unix__被预定义了是可以理解的,按一般惯例,用户不会也不应该在自己的标识符前后加上下划线,但问题是unix、linux、i386、i586也被预定义了,编译报语法错,郁闷啊。

PS:请在你的机器上(LINUX平台或者CYGWIN)测下如下的代码,然后把结果贴出来,好吗?

  1. int unix;
  2. int linux;
  3. int i386;
  4. int i586;

  5. int main()
  6. {
  7.      return 0;
  8. }
复制代码

论坛徽章:
0
7 [报告]
发表于 2009-02-10 15:21 |只看该作者
加个前缀得了……

论坛徽章:
0
8 [报告]
发表于 2009-02-10 15:27 |只看该作者
原帖由 langue 于 2009-2-10 15:21 发表
加个前缀得了……

我原来的程序是想学习下c++的多继承的,正好solaris继承与bsd和system V,很自然就写出了如下代码:

  1. class unix {
  2. }

  3. class linux: unix {
  4. }

  5. class bsd: unix {
  6. }

  7. class system: unix {
  8. }

  9. class solaris: bsd, system {
  10. }
复制代码

在我的FC5上死活编译不过去,郁闷,后来想到用cpp看下,发现unix、linux被替换成1了。

[ 本帖最后由 CRLF 于 2009-2-10 15:28 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2009-02-10 15:33 |只看该作者

回复 #8 CRLF 的帖子

想法不错,不过还是建议拿 Java 练习 OO 吧。C++ 多了 C 的羁绊,不便之处真的有很多。C++ 的优越性不在 OO,而是和 C 语言的互操作性,所以更适合系统编程。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
10 [报告]
发表于 2009-02-10 15:40 |只看该作者
我有一次在solaris平台上定义一个enum类型,用到了sun,
结果……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP