7

我经历了这个问题 -

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

它有什么不同?应该是0(int*)0
如何检查结果?
我们可以在哪里使用这种类型的表达?

4

2 回答 2

19

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

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

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

(强调我的)

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

值为 0 的整数常量表达式,或转换为 type 的此类表达式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)但结果不同。

我们可以在哪里使用这种类型的表达方式?

我想不出语言的这个晦涩角落的有用和具体用途。

于 2012-12-30T19:59:14.510 回答
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  )));
于 2012-12-30T20:55:36.730 回答