前言

众所周知,C语言本身没有多态的概念,函数也没用重载的概念。 而在动态类型的语言里面,往往有typeof这种语法,来获取变量的数据类型。例如,JavaScript当中,typeof以字符串型式返回了这个变量的数据类型;python中有type()的方法来获取变量类型。借由这种特性,往往可以根据传入参数的类型不同,产生不同的行为。

C语言标准并不支持typeof的语法,但是gcc扩展是支持typeof语法的。

可以查看gcc对于typeof的说明

用法

1
2
3
int a;
typeof(a) b;  //相当于 int b;
typeof(&a) c;  //相当于int *c;

也可以直接使用类型作为参数: typeof(int *)

用途

在linux源码中,typeof被用来实现一个安全的max和min宏定义。 在include /linux/kernel.h中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#define min(x, y) ({				\
	typeof(x) _min1 = (x);			\
	typeof(y) _min2 = (y);			\
	(void) (&_min1 == &_min2);		\
	_min1 < _min2 ? _min1 : _min2; })

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

可以看出,linux使用typeof获取传入的x和y的类型,然后定义局部变量以消除参数副作用。

注意中间的比较操作 (void) (&_max1 == &_max2) 与 (void) (&_min1 == &_min2) 这两行代码是用来做类型检查的,如果x和y的类型不同,那么编译器将提示如下警告信息,这对检查代码很有帮助。 xxx.c:35: warning: comparison of distinct pointer types lacks a cast 这个类型检查是怎么回事呢? 简单来说,在C99标准的第6.5.9节中规定,对于比较运算符 == 和 != 来说,如果比较的对象是指针,那么指针所指的对象类型必须一致,否则抛出上面的warning信息.

GCC对Typeof的处理

GCC提供的typeof,实际上是在预编译时处理的,最后实际转化为数据类型被编译器处理。

参考链接: 6.6 Referring to a Type with typeof 藝術與核心