详解 GNU C 标准中的 typeof 关键字

版权声称:定冠词是视频博客作者的怪人文字。,请解说其创作。。

免得你是 C++ 程序员,一定尝。 C++11 里的 decltype 伪造符,它的功用是志愿地派生表情的数据典型,处理泛型课程击中要害相当成绩(即便是IM)。现实上,上面所说的事得分是 C 类推的取得先前在讲中取得。,GNU C 规范击中要害伸出特点 typeof (PS) 变动从而产生断层 Typedef)作用与 decltype 类推,让咱们看一眼上面所说的事关键词一定健康状况如何运用。。

让咱们风景最简略的例。:

// demo 01
int var = 666;
typeof(int) *) pvar = &var;
printf("pvar:\t%p\n", pvar)
Prtf(and var:\t%p\n), var)
Prtf(var:\t%d\n), var)
printf("*pvar:\t%d\n", *pvar)

咱们率先构成释义了本人。 int 型变量 var,过后构成释义用手指触摸变量暴露。 var,大体上,咱们是指示方向的。 int *xxx = &xx,但咱们必须做的事使发誓。 typeof 的用法,别这么开门见山。,typeof 志愿地推退 ( ) 数据典型,因而 typeof(int) *) 它是指示方向派生摆脱的。 int * 型,用这种典型声称 pvar 并将其设定初值为 var 的地址,出口一定是聪明的的。,这是我机具上的出口。:


嗯,我识别上面的例是吃力不讨好的。,清楚地写个 int * 简略明了。,不得不加 typeof 真是不著名的艰深晦涩。,确实 typeof 其功用是可以志愿地导出表情典型。,譬如咱们把现在的 typeof(int) *) 改成 typeof(&var),它也会志愿地推断摆脱。 &var 的典型 —— int * 型,你可以本人试试看。,基本是相等地的。,大约本人词,当屈尊做某事本人充分复杂的表达时,咱们很难推断。,typeof 这很有帮助的。。仍少数必要理睬。:typeof
是 GNU C 规范伸出,规范的 ISO C 心不在焉大约的关键词。,因而编辑时不克不及添加任何的质地。 ISO 的 C 规范调动球员,要不,你将告发有毛病的。,诸如,编辑上面的加密,我预了内侧本人。 -std=c90 的调动球员,编辑器会准时的一堆。 error:


处理方法很简略。,把 -std=c90 改成 -std=gnu90 即 GNU 规范可以。

上面是更多的例。,譬如

// demo 02
int *pvar = NULL;
typeof(*pvar) var = 999;
Prtf(var:\t%d\n), var)

上面所说的事例率先构成释义了本人完整的用手指触摸变量。 pvar,typeof 插入成分击中要害表情为*PVAR。,pvar 典型是 int * 型,那 *pvar 自然,它被解说为 int 型,因而,声称具有这种典型的变量。 var 也 int 型,相当于 int var = 999; 出口列举如下:


重现:

// demo 03
int *pvar = NULL;
typeof(*pvar) VaR〔4〕 = {11, 22, 33, 44};
for (int) i = 0; i < 4; i++)
	printf("var[%d]:\t%d\n", i, var[i]);

这次 typeof 分辨能力的典型与本人俱。,不同之处分娩 var 它是本人容纳四的元素的大楼。,相当于 int VaR〔4〕 = {...}; 出口列举如下:

这次有少数点。:

// demo 04
typeof(typeof(const char *)[4]) pchar = {表示问候, "world", "good", 夜}
for (int) i = 0; i < 4; i++)
	printf("pchar[%d]:\t%s\n", i, pchar[i]);

这次出现相当复杂。,是时分棘手的你的用手指触摸了。,他嵌套了两层。 typeof,咱们本人本人地向外剥皮。,先看最内层。,typeof 率先辨析本人。 const char * 典型,有亲身经历的 C 程序员一定可以同时故意的字母行。,被钩住是另本人。 [4],这是本人容纳四的字母行的大楼典型。,这种典型也最外界。 typeof 解析它。,因而不可更改的。 pchar 这执意典型。,相当于 const char *pchar[4] = {...}; 

再次棘手的用手指触摸。,这是作用用手指触摸。:

// demo 05
int add(int) param1, int param2) {
	return param1 + param2;
}

int sub(int) param1, int param2) {
	return param1 - param2;
}

int mul(int) param1, int param2) {
	return param1 * param2;
}

int main() {
	int FUNC〔3〕 (int), int) = {添加, sub, mul};
	typeof(FUNC〔0〕(1, 1)) sum = 100;
	typeof(func[1](1, 1)) dif = 101;
	typeof(func[2](1, 1)) pro = 102;

PANTF(和:\t%D\n), 和)
DIF:\t%D\n, DIF)
PROTF(PRO:\t%D\n), PRO)
	return 0;
}

上面所说的事 demo 率先构成释义了三个作用。,这三个作用都是重新提起值。 int 典型,承担两个。 int 典型参量,过后在 main 作用中构成释义了作用用手指触摸大楼。 func,并运用上面三个作用名设定初值它。,让咱们看一眼上面的第本人。 typeof 将导出什么典型?,FUNC〔0〕 执意指 add 上面所说的事作用,插入成分遵照两个参量。,简略地说,这很简略。 添加(1), 1) 的命令,而 add 它将重新提起到本人。 int 型值,因而终极推断出的典型是 int 型,此外两个是相等地的。,因而 sum、dif、pro 现实上,有三个完整的。,相当于
int sum = 100; int dif = 101; int pro = 102; 好吧,我识别这少数。 demo 凹坑,上面所说的事例是不妥的。,出口是它们各自的值。:


让咱们看一眼它在宏构成释义击中要害申请。:

// demo 06
#define 用手指触摸(t)  typeof(T *)
#define 大楼(t), N) typeof(T[N])

int main() {
大楼(用手指触摸(char)), 4) pchar = {表示问候, "world", "good", 夜}
	for (int) i = 0; i < 4; i++)
		printf("pchar[%d]:\t%s\n", i, pchar[i]);
	return 0;
}

在这里运用宏作用。,用手指触摸(t) 将被代替 typeof(T *),也执意说 pointer 其次是一种典型的名字。,预支后,它将抓住有帮助的。 typeof 解析对应典型的用手指触摸典型,而 array 前面跟着本人典型名和本人完整的。,过后 typeof 它将被解析为这种典型的大楼。,大约 main 作用击中要害大楼(用手指触摸(char)), 4),用手指触摸(使具有特征) 率先,它将被解说为 char * 型,过后是外界。 array 将推动解说为容纳。 4 个 char * 元素大楼典型,因而相当于 char
*pchar[4] = {...}; 出口列举如下:


好了,深深地。,typeof 上面所说的事关键词算是意识该怎地做了。,觉得式很含糊。,同时心不在焉现实作用。,那好吧,让我给你演示一下现实以协议约束的另本人例。:

/*
 * 选自  内核源码
 * filename: /include/linux/
 */
#define 分钟(X),y) ({ \
	typeof(x) _x = (x);	\
	typeof(y) _y = (y);	\
(病号) (&_x == &_y);		\
	_x < _y ? _x : _y; })

上面的例是从 linux 2.6.7 内核中容纳/Linux 上面所说的事头文档,宏构成释义 min 其功用是从类似典型的两个目的中选择最小的本人。,它承担两个参量。 x 和 y,他日将运用宏的掉换部件。 typeof 构成释义两个变量 _x 和 _y,并将它们分派为 x y,上面是运用 typeof 功用是让 min 承担任何的类典型参量而不用禁闭某本人单一典型,这是本人泛型课程。,终于本人表现 < _y ? _x : _y; 用了本人条件运算符来重新提起二者之中最小的,中间仍一句(病号) (&_x == &_y); 出现好像是废话,确实这句话是有特殊用意的,因为咱们不克不及保证你在运用 min 的时分传入的两个参量都是俱的典型,这时分就必要做本人检测,而 C 讲不支持指示方向 typeof(_x) == typeof(_y) 大约的伪造,因而就取其地址,用用手指触摸典型来比较,免得两个用手指触摸的典型不一致,编辑器就会产生警告以达到检测的效果,至于前面的 (void),是因为仅表情 &_x == &_y 本身是心不在焉意义的,免得心不在焉上面所说的事 (void) 编辑器同样会警告:statement with no effect [-Wunused-value],病号的表现,免得不想看到上面所说的事警告,那就在前面加个

(病号) 疏忽掉。

参考资料:

GNU 行政官员手册:

发表评论