7

私はこの質問に答えました-

1 ? (int *)0 : (void *)0
:の結果が:の結果と異なる 理由1 ? (int *)0 : (void *)1

どう違うの?0またはである必要があります(int*)0
結果を確認する方法は?
そのようなタイプの表現をどこで使用できますか?

4

2 に答える 2

19

唯一の違いはタイプにあります。最初のタイプはを返しint *、2番目のタイプはを返しますvoid *

C11標準から、§6.5.15条件演算子、¶6:

2番目と3番目のオペランドの両方がポインターであるか、一方がnullポインター定数で、もう一方がポインターである場合、結果の型は、両方のオペランドによって参照される型のすべての型修飾子で修飾された型へのポインターです。さらに、両方のオペランドが互換性のある型または互換性のある型の異なる修飾バージョンへのポインターである場合、結果の型は複合型の適切に修飾されたバージョンへのポインターになります。一方のオペランドがnullポインター定数の場合、結果はもう一方のオペランドのタイプになります。それ以外の場合、1つのオペランドは、のポインタvoidまたは修飾バージョンですvoid。この場合、結果タイプは、の適切に修飾されたバージョンへのポインタですvoid

(強調鉱山)

非へのポインタはnullポインタ定数ではなく、 nullvoidポインタであることに注意してください。C11§6.3.2.3ポインター、¶3:

値が0の整数定数式、または型にキャストされるそのような式は、 nullポインター定数void *と呼ばれます。66) nullポインター定数がポインター型に変換される場合、nullポインターと呼ばれる結果のポインターは、任意のオブジェクトまたは関数へのポインターと等しくないことが保証されます。

66)マクロNULL<stddef.h>(および他のヘッダーで)nullポインター定数として定義されています。7.19を参照してください。

だから、ここで:

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

(int *) 0は単なるnullポインタ(void *) 0あり、はnullポインタ定数であるため、結果は型になりますint *( "一方のオペランドがnullポインタ定数の場合、結果はもう一方のオペランドの型になります")。

ここにいる間:

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

nullポインター定数がないため(最初のnullポインターのみ)、結果は複合型になりますvoid *( "両方のオペランドが互換性のある型または互換性のある型の異なる修飾バージョンへのポインターである場合、結果の型は複合型の適切に修飾されたバージョン")。

結果にはさまざまなタイプがありますが、どちらもnullポインターです。また、結果は質問で言うようには決してならず 0、常にポインタであることに注意してください。

残念ながら、Cの違いを確認する標準的な方法はありません。C++はそれについてある程度サポートしています(typeinfo)が、結果はそこで異なります。

このような表現はどこで使えますか?

言語のこのあいまいなコーナーの有用で具体的な使用法について考えることはできません。

于 2012-12-30T19:59:14.510 に答える
4

したがって、effeffeは、2つの式が異なる理由についてすでに回答しています。

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 に答える