Chinaunix首页 | 论坛 | 博客
  • 博客访问: 297561
  • 博文数量: 103
  • 博客积分: 2345
  • 博客等级: 大尉
  • 技术积分: 902
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-01 09:10
文章分类

全部博文(103)

文章存档

2022年(1)

2018年(3)

2017年(2)

2016年(3)

2015年(8)

2014年(8)

2013年(2)

2012年(9)

2011年(29)

2010年(20)

2009年(18)

我的朋友

分类:

2011-06-15 15:34:44

从一个简单的宏定义看linux内核的严谨,窥C语言的强大
 
对 typeof 的理解:

实际上, typeof 并不是宏定义,它是GCC的关键字,是GCC特有的特性。如果只知道一个变量的名字要得到其类型,并不是宏定义能够完成的,这需要编译时的信息。所以,typeof 操作是GCC内置的功能,在内核头文件和Glibc头文件中都是找不到typeof的宏定义的。
 

include/linux/kernel.h
------------------------------------------------------
/*
 * min()/max() macros that also do
 * strict type-checking.. See the
 * "unnecessary" pointer comparison.
 */
#define min(x,y) ({         \
    typeof(x) _x = (x);     \
    typeof(y) _y = (y);     \
    (void) (&_x == &_y);    \
    _x < _y ? _x : _y; })

#define max(x,y) ({         \
    typeof(x) _x = (x);     \
    typeof(y) _y = (y);     \
    (void) (&_x == &_y);    \
    _x > _y ? _x : _y; })

 

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

------------------------------------------------------

#include

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

int main ()
{
    min(10, 20);
    if (1)
        min(10, 20);
    return 0;
}


------------------------------------------------------
#include

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

int main ()
{
    int ret;
    ret = min(10, 20);
    printf("ret = %d\n", ret);
    return 0;
}

------------------------------------------------------
#include

/*
 * 检测变量类型是否相同
 * (void) (&_min1 == &_min2);
 */
#define min(x, y) ({                      \
    typeof(x) _min1 = (x);                \
    typeof(y) _min2 = (y);                \
    (void) (&_min1 == &_min2);            \
    _min1 < _min2 ? _min1 : _min2; })

int main ()
{
    int  ret;
    int  i;
    char j;
    ret = min(i, j);
    printf("ret = %d\n", ret);
    return 0;
}

------------------------------------------------------
#include

/*
 * 防止类似i++类型的参数,被重复计算
 * typeof(x) _min1 = (x);
 */
#define min(x, y) ({                      \
    typeof(x) _min1 = (x);                \
    typeof(y) _min2 = (y);                \
    (void) (&_min1 == &_min2);            \
    _min1 < _min2 ? _min1 : _min2; })

int main ()
{
    int ret;
    int i = 100;
    int j = 200;
    ret = min(i++, j++);
    printf("ret = %d\n", ret);
    return 0;
}


------------------------------------------------------
#include

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

int main ()
{
    min(10, 30);
    return 0;
}

 

------------------------------------------------------
#include

int main ()
{
    int  i;
    char j;
    /*
     * 通过下面测试证明,取址操作获取的地址是有类型的
     * &i 获取的地址类型为 int  *
     * &j 获取的地址类型为 char *
     */
    printf("&i   = %p\n", &i);
    printf("&i+1 = %p\n", &i+1);
    printf("&j   = %p\n", &j);
    printf("&j+1 = %p\n", &j+1);

    (void)(&i == &j);
    return 0;
}



$ gcc test.c
test.c: 在函数‘main’中:
test.c:17: 警告: 比较不相关的指针时缺少类型转换
$ ./a.out
&i   = 0xbfeccbac
&i+1 = 0xbfeccbb0
&j   = 0xbfeccbb3
&j+1 = 0xbfeccbb4


阅读(853) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~