您的位置:首页 > 运维架构 > Linux

从一个简单的宏定义看linux内核的严谨,窥C语言的强大(ZZ

2013-06-10 17:47 218 查看
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 <stdio.h>

/* 使用该宏时,如果不关心返回值,没有圆括号()也可以,但是{}是必须的 */

#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 <stdio.h>

/*

 * 用该宏时,如果关心返回值,就必须要圆括号()

 * 最后一句是该宏的返回值

 */

#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 <stdio.h>

/*

 * 检测变量类型是否相同

 * (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 <stdio.h>

/*

 * 防止类似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 <stdio.h>

/*

 * 这种写法,利用了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 <stdio.h>

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux