实上并没有。我们该怎么定义result_type?对于浮点数类型我们可以直接用__typeof__ (X),但我们又想用double作为整形参数,况且C语言并没有一种对于类型的? :操作数,是吧。
前两个练习放在那儿,并不是因为我是个老师,想检查一下你的进度。它们是为了最后最有难度的习题准备的——或者是为了在你到这里之前就把你吓跑。(好吧,我想我已经把大家都无聊死了,没人能读到这儿了。)虽然这个习题的上下文提示的已经够多了,也可能仍然不足以解答,来看看吧:
困难的习题:以下两个结果有何不同?
和
以及为什么?
不像之前的两个习题稍作研究和思考就能解决,这个习题(尤其是为什么的部分)有可能要求你阅读C语言标准,因此我在这里做出解释。
首先,解释一下概念是必要的:
从编译器的角度来说,一个整形常数表达式就是一个整形表达式有一个常数值:编译器能够计算这个常数而不用任何除了常数合并以外的优化。尤其是这个表达式不会用到任何其他变量的值。
空指针就是一个值等于整数值0的指针。空指针能够是任何类型的指针。
空指针常量是一种句法结构。空指针常量的值在转换成一个指针类型时,是一个空指针(“空指针”和“它的值”都在上文说过了)。空宏展开成空指针。
因为空指针常量是一种句法结构,它就有一个句法定义,它要不是一个等于零的整型常量,要不一个转换成void *的表达式。举个例子,0, 0L, 1 - 1, (((1 - 1))), (void *)和(void *)(1 - 1)都是空指针常量,但(int *)0和(void *)1就不是。
(其实,当其定义为一个表达式的值时,它就不是一个句法结构了。不过最好就这样假装它是个句法结构,因为大部分情况下,“值为零的整型常量表达式”其实就是字面上的0。)
现在我们来看看C语言标准的6.5.15部分的第六段,这部分讲到了条件操作符? :,有以下内容:
如果第二和第三操作数都是指针…,那么结果类型也会是一个指针…。更有,如果两个操作数都是指向类型相兼容的指针的话…,结果类型会是一个…指向其合成类型的指针;如果一个操作数是一个空指针常量,结果类型跟另一个操作数的类型相同;否则,…结果类型是一个指向void…的指针。
因此,在下面表达式中
第三个操作数是一个空指针常量,因此结果是(int *)0。而在
中,第三个操作数不是一个空指针常量,因此结果是。这就是我们对于类型的条件操作符,我们只需再稍加修缮。
注意到这个表达式(其中X是个整形)是一个整形常量表达式。
? (__typeof__ (X) *)0 : (void *)(X has a integer type)
因此,如果X是一个整形变量,结果就是(void *)0,否则就是。而下面这个式子。
? (int *)0 : (void *)(!(X has an integer type))
在X是整形的情况下结果是(int *)0,否则结果是(void *)0。注意到两个情况中都有其中一个结果是(void *)0。
我们定义上面两个表达式分别为E1和E2,那么,以下表达式:
? (__typeof__ (E1))0 : (__typeof__ (E2))0
在x是整形的时候为(int *)0,否则为(__typeof__ (X) *)0。同上,我们注意到有一个表达式总是空指针常量。
最后,我们定义result_type为:
__typeof__ (*(1 ? (__typeof__ (E1))0 : (__typeof__ (E2))0))
这就对了。对于多于一个参数的宏来说会稍微复杂一点,不过基本概念和方法都和上面描述的一样。
博主是一个有着7年工作经验的架构师,对于c++,自己有做资料的整合,一个完整学习C语言c++的路线,学习资料和工具。可以进我的Q群7418,18652领取,免费送给大家。希望你也能凭自己的努力,成为下一个优秀的程序员!另外博主的微信公众号是:C语言编程学习基地,欢迎关注!