三元运算符和类型转换中的混淆

时间:2012-12-30 19:49:09

标签: c type-conversion ternary-operator void-pointers

我经历了这个问题 -

为什么结果:1 ? (int *)0 : (void *)0
与以下结果不同: 1 ? (int *)0 : (void *)1

它有何不同?它应该是0(int*)0 如何查看结果?
我们可以在哪里使用这种表达方式?

2 个答案:

答案 0 :(得分:19)

唯一的区别在于类型:第一个返回int *,第二个返回void *

从C11标准,§6.5.15条件运算符,¶6:

  

如果第二个和第三个操作数都是指针,或者一个是空指针常量而另一个是指针,则结果类型是指向使用两个操作数引用的类型的所有类型限定符限定的类型的指针。 此外,如果两个操作数都是兼容类型的指针或兼容类型的不同限定版本,则结果类型是指向复合类型的适当限定版本的指针;如果一个操作数是空指针常量,则结果具有另一个操作数的类型;否则,一个操作数是 void 的指针或 void 的限定版本,在这种情况下,结果类型是指向适当的指针合格版 void

(强调我的)

请记住,指向非void的指针不能是空指针常量,而只能是空指针。 C11§6.3.2.3指针,¶3:

  

值为0的整型常量表达式,或者类型为 void * 的表达式,称为空指针常量 66 )如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较。

     

66)宏 NULL <stddef.h> (以及其他标题)中定义为空指针常量;见7.19。

所以,在这里:

1 ? (int *) 0 : (void *) 0

(int *) 0只是空指针,而(void *) 0空指针常量,因此结果的类型为int *( “如果一个操作数是空指针常量,则结果具有另一个操作数的类型”。

在这里:

1 ? (int *) 0 : (void *) 1

没有空指针常量(只有空指针,第一个),因此结果具有复合类型void *(“如果两个操作数都是兼容类型的指针或兼容类型的不同限定版本,则结果类型是指向复合类型的适当限定版本的指针“)。

结果有不同的类型,但它们都是空指针。另请注意,结果是从不 0正如您在问题中所说,它始终是指针。

不幸的是,没有标准的方法可以看出C中的差异,C ++对它有一些支持(typeinfo)但结果却有所不同。

  

我们可以使用这种表达方式吗?

我无法想到这种模糊不清的语言角落的有用和具体用法。

答案 1 :(得分:4)

所以effeffe已经回答了两个表达式不同的原因:

1 ? (int *) 0 : (void *) 0  // yield (int *) 0
1 ? (int *) 0 : (void *) 1  // yield (void *) 0

现在回答这个问题:

  

如何检查结果?

使用gcc,您可以使用typeof扩展名和__builtin_types_compatible_p内置函数:

// The two expressions differ
printf("%d\n", __builtin_types_compatible_p(typeof(1 ? (int *) 0 : (void *) 0), typeof(1 ? (int *) 0 : (void *) 1)));

// First expression yield (int *) 0
printf("%d\n", __builtin_types_compatible_p(typeof((int *) 0), typeof( 0 ? (int *)0 : (void *)0  )));

// Second expression yield (void *) 0
printf("%d\n", __builtin_types_compatible_p(typeof((void *) 0), typeof( 1 ? (int *)0 : (void *)1  )));