Chinaunix首页 | 论坛 | 博客
  • 博客访问: 342985
  • 博文数量: 56
  • 博客积分: 2058
  • 博客等级: 中尉
  • 技术积分: 688
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-11 09:19
个人简介

code rush

文章分类

全部博文(56)

文章存档

2012年(2)

2011年(54)

分类: LINUX

2011-08-03 14:09:14

  1. /*
  2.  * min()/max() macros that also do
  3.  * strict type-checking.. See the
  4.  * "unnecessary" pointer comparison.
  5.  */
  6. #define min(x,y) ({ \
  7.     typeof(x) _x = (x); \
  8.     typeof(y) _y = (y); \
  9.     (void) (&_x == &_y); \
  10.     _x < _y ? _x : _y; })

  11. #define max(x,y) ({ \
  12.     typeof(x) _x = (x); \
  13.     typeof(y) _y = (y); \
  14.     (void) (&_x == &_y); \
  15.     _x > _y ? _x : _y; })

  16. (void) (&_x == &_y)
  17. 这句不是为了判断两个变量的地址是否相等,而是为了判断两个变量的类型是否相同;
  18. 如果类型不同,编译阶段,编译器为告警!

  19. ------------------------------------------------------

  20. #include <stdio.h>

  21. /* 使用该宏时,如果不关心返回值,没有圆括号()也可以,但是{}是必须的 */
  22. #define min(x, y) { \
  23.     typeof(x) _min1 = (x); \
  24.     typeof(y) _min2 = (y); \
  25.     (void) (&_min1 == &_min2); \
  26.     _min1 < _min2 ? _min1 : _min2; }

  27. int main ()
  28. {
  29.     min(10, 20);
  30.     if (1)
  31.         min(10, 20);
  32.     return 0;
  33. }



  34. ------------------------------------------------------
  35. #include <stdio.h>

  36. /*
  37.  * 用该宏时,如果关心返回值,就必须要圆括号()
  38.  * 最后一句是该宏的返回值
  39.  */
  40. #define min(x, y) ({ \
  41.     typeof(x) _min1 = (x); \
  42.     typeof(y) _min2 = (y); \
  43.     (void) (&_min1 == &_min2); \
  44.     _min1 < _min2 ? _min1 : _min2; })

  45. int main ()
  46. {
  47.     int ret;
  48.     ret = min(10, 20);
  49.     printf("ret = %d\n", ret);
  50.     return 0;
  51. }


  52. ------------------------------------------------------
  53. #include <stdio.h>

  54. /*
  55.  * 检测变量类型是否相同
  56.  * (void) (&_min1 == &_min2);
  57.  */
  58. #define min(x, y) ({ \
  59.     typeof(x) _min1 = (x); \
  60.     typeof(y) _min2 = (y); \
  61.     (void) (&_min1 == &_min2); \
  62.     _min1 < _min2 ? _min1 : _min2; })

  63. int main ()
  64. {
  65.     int ret;
  66.     int i;
  67.     char j;
  68.     ret = min(i, j);
  69.     printf("ret = %d\n", ret);
  70.     return 0;
  71. }

  72. ------------------------------------------------------
  73. #include <stdio.h>

  74. /*
  75.  * 防止类似i++类型的参数,被重复计算
  76.  * typeof(x) _min1 = (x);
  77.  */
  78. #define min(x, y) ({ \
  79.     typeof(x) _min1 = (x); \
  80.     typeof(y) _min2 = (y); \
  81.     (void) (&_min1 == &_min2); \
  82.     _min1 < _min2 ? _min1 : _min2; })

  83. int main ()
  84. {
  85.     int ret;
  86.     int i = 100;
  87.     int j = 200;
  88.     ret = min(i++, j++);
  89.     printf("ret = %d\n", ret);
  90.     return 0;
  91. }

  92.  

  93. ------------------------------------------------------
  94. #include <stdio.h>

  95. /*
  96.  * 这种写法,利用了do while的巧妙之处,但是也有最大一个缺憾,无法获得该宏的返回值;
  97.  * 如果只想实现一组语句的正确执行,而不关心其返回值,可以使用do while;
  98.  * 但是如果想获取这组语句的返回值,则必须使用(){},将返回值放在最后一句。
  99.  */
  100. #define min(x, y) \
  101. do { \
  102.     typeof(x) _min1 = (x); \
  103.     typeof(y) _min2 = (y); \
  104.     (void) (&_min1 == &_min2); \
  105.     _min1 < _min2 ? _min1 : _min2; \
  106. } while (0)

  107. int main ()
  108. {
  109.     min(10, 30);
  110.     return 0;
  111. }


  112. ------------------------------------------------------
  113. #include <stdio.h>

  114. int main ()
  115. {
  116.     int i;
  117.     char j;
  118.     /*
  119.      * 通过下面测试证明,取址操作获取的地址是有类型的
  120.      * &i 获取的地址类型为 int *
  121.      * &j 获取的地址类型为 char *
  122.      */
  123.     printf("&i = %p\n", &i);
  124.     printf("&i+1 = %p\n", &i+1);
  125.     printf("&j = %p\n", &j);
  126.     printf("&j+1 = %p\n", &j+1);

  127.     (void)(&i == &j);
  128.     return 0;
  129. }


  130. $ gcc test.c
  131. test.c: 在函数‘main’中:
  132. test.c:17: 警告: 比较不相关的指针时缺少类型转换
  133. $ ./a.out
  134. &i = 0xbfeccbac
  135. &i+1 = 0xbfeccbb0
  136. &j = 0xbfeccbb3
  137. &j+1 = 0xbfeccbb4
阅读(1760) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

zhangxing31342011-12-13 10:48:32

do while运行一组语句的时候可以在if后面不加{}而不会产生错误,另外do while的行末必须加分号使得宏作为一个语句使用,显得程序严谨。刷一分