第一种实现实现 :
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
第二种实现:
#define TYPE_EQUAL(n, type) \
__builtin_types_compatible_p(typeof(n), type *)
------------
且看kernel里面的例子:
关于 montavista-kernel-2.6.18_pro500
#define PICK_OP(op, lock) \
do { \
if (TYPE_EQUAL((lock), raw_spinlock_t)) \
__spin##op((raw_spinlock_t *)(lock)); \
else if (TYPE_EQUAL(lock, spinlock_t)) \
_spin##op((spinlock_t *)(lock)); \
else __bad_spinlock_type(); \
} while (0)
#define spin_lock_irq(lock) PICK_OP(_lock_irq, lock)
#define spin_lock_bh(lock) PICK_OP(_lock_bh, lock)
在kernel 里面不太好验证:
我写了一个简单的程序来玩玩:
GNU的扩展语法真的比较强, 必 ANSI C强多了。
功能需求: 实现一个通用的打印函数, 可以打印所有的变量。
#include
#include
#define TYPE_EQUAL(n, type) \
__builtin_types_compatible_p(typeof(n), type *)
#define PICK_OP_PRINT(op, n) \
do { \
if (TYPE_EQUAL((n), int)) \
printf("int number=%d\n",*n); \
else if (TYPE_EQUAL(n, long)) \
printf("long number=%ld\n",*n); \
else \
printf("error\n"); \
} while (0)
#define printtype(n) PICK_OP_PRINT(op, n)
int main(void)
{
int a = 20;
printtype(&a);
long b = 100000000;
printtype(&b);
float c = 3.6L;
printf("float c=%f\n",c);
printtype(&c);
return 0;
}
输出结果如下:
[root@bobzhanglinux debug]# gcc spinlock.c
[root@bobzhanglinux debug]# ./a.out
int number=20
long number=100000000
float c=3.600000
error
[root@bobzhanglinux debug]#
我们在kernel的代码里面经常会看到定义宏的时候, 会有这样的格式:
#define A ({ a }) 一般都是定义类函数宏的时候 才这样的, 这样在里面可以加这些语句体 , 然后返回一些值 ,
最后, 不要return , 从来看不到return这样的字样 。 具体的我们也没有必要深究的。 只要模仿着写一些常用的好类函数宏, 就好了。
比如下面的例子:
#define PICK_OP_PRINT(op, n) \
({ \
if (TYPE_EQUAL((n), int)) \
printf("int number=%d\n",*n); \
else if (TYPE_EQUAL(n, long)) \
printf("long number=%ld\n",*n); \
else \
printf("error\n"); \
})
象上面这个类函数宏,也可以写成这个样子:
#define PICK_OP_PRINT(op, n) \
do { \
if (TYPE_EQUAL((n), int)) \
printf("int number=%d\n",*n); \
else if (TYPE_EQUAL(n, long)) \
printf("long number=%ld\n",*n); \
else \
printf("error\n"); \
} while (0)
以上情况,都是适合不要返回值的情况下。
--------------------
如果要返回值, 我看就只能用 ({})
就不能用do{}while(0) ,这种比较适合写类函数宏
----
比如下面的例子:就只能用 ({}) 了。
要返回一个值:
#define PICK_OP2_RET(op, lock, flags) \
({ \
unsigned long __ret; \
\
if (TYPE_EQUAL((lock), raw_spinlock_t)) \
__ret = __spin##op((raw_spinlock_t *)(lock), flags); \
else if (TYPE_EQUAL(lock, spinlock_t)) \
__ret = _spin##op((spinlock_t *)(lock), flags); \
else __bad_spinlock_type(); \
\
__ret; \
})