不完全な型へのポインタは不完全なのでしょうか?


9

することができint (*)[]、不完全型で?

C 2018 6.2.5 1は言う:

翻訳単位内のさまざまな時点で、オブジェクトタイプは不完全(そのタイプのオブジェクトのサイズを決定するのに十分な情報がない)または完全(十分な情報がある)の場合があります。

したがって、型のサイズがわかっていれば、型は完全であるように見えます。6.2.6.1 28は、特定のタイプのポインターは同じサイズ(ポインターvoidと文字、互換タイプへのポインター、構造体へのポインター、および共用体へのポインター)でなければならないことを指定していますが、他のタイプへのポインターは異なる場合があります。

すべてのポインター、またはの配列へのすべてのポインターがint同じサイズであるCの実装では、のサイズint (*)[]がわかっているため、完全なサイズになります。たとえば、大きな配列に異なるポインタを使用する実装では、サイズがわからないため、不完全です。

以下のようにMMが指摘し、構造これは、ポインタのサイズの実装が受け入れなければならないことを示唆している6.7.2.1 3に制約ごとに、最終的な可撓性のアレイメンバーを除き、不完全な型とメンバーを含んではならないstruct { int (*p)[]; }異なる有する実装ながらそのような配列のサイズは、制約違反を診断する必要があります。(これは、そのような宣言が厳密に準拠するCの一部ではないことを意味します。)


6.2.5(p22)ヘルプ?(または、それにより混乱が増し、不完全な型が後の宣言で完成できるようになりますか?)
David C. Rankin

@ DavidC.Rankin 6.2.5 / 20では、ポインタは常に完全な型であるとも言われています
Christophe

@LanguageLawyer:それはどのように関連していますか?問題は、「YではないXはありますか?」ではなく、「YであるXはありますか?」
Eric Postpischil

@LanguageLawyer:void *完全であるという事実は、不完全な型へのポインタが完全である可能性があることを示しています。不完全な型へのポインタが不完全である可能性があるかどうかは示しません。「哺乳動物は象になれるのか」と尋ねられた場合、「ライオンは哺乳動物である」と示しても、哺乳動物が象になることはできません。質問は、不完全な型へのポインターのセットXに不完全な要素が含まれているかどうかを尋ねます。不完全な型へのポインタのセットXに完全な要素が含まれていることを示すことは無関係です。
Eric Postpischil

@EricPostpischilおっと。タイトルを「不完全な型へのポインタを完全にすることはできますか?」と誤解しました。
言語弁護士

回答:


3

不明なサイズの配列は不完全です:

サイズが不明な配列型は不完全型です。そのタイプの識別子については、後の宣言でサイズを指定することにより(内部リンクまたは外部リンクを使用して)完了します。

int (*)[]ただし、型は不完全ではありませんint。サイズが不明な配列のポインタです。
そして、ポインタにはよく知られたサイズがあります:

printf ("Size %d\n", sizeof(int (*)[]));

6.2.5 / 23:型が不完全ではなく、可変長配列型でない場合、型は既知の定数サイズを持ちます。

さらに、配列のセマンティクスのおかげで、逆参照することもできます。

typedef int (*T)[];
...
int a[10];
for (int i=0; i<10; i++) a[i]=i;
T p=a;
for (int i=0; i<10; i++) printf ("%d ",(*p)[i]);
printf ("\n");

編集する

さらに、ポインターは常に完全な型です。6.2.5 / 20では白地に黒で書かれています。

ポインタ型は、参照される型と呼ばれる関数型またはオブジェクト型から派生できます。ポインタ型は、値が参照される型のエンティティへの参照を提供するオブジェクトを表します。参照される型Tから派生したポインター型は、「Tへのポインター」と呼ばれることもあります。参照される型からのポインター型の構築は、「ポインター型の派生」と呼ばれます。ポインタ型は完全なオブジェクト型です。


私はあなたがそれを煮詰めたと思います、そしてgccは同意します。不完全な配列へのポインタを含む構造体は、議論を促す元の質問に似ています。
デビッドC.ランキン

関連するのは最後の段落のみです。この例printfは、質問で述べたように、不完全な配列へのポインターが、それが実行された実装で完全であることを示しています。それが6.2.5 20でない場合は、前の段落で引用されているように、コンパイルに失敗する可能性があります。6.2.5 23も関係ありません。これは、サイズが既知であり、それが完全であれば一定であることを示します。完全であるということは、サイズが既知であることをすでに知っています。
Eric Postpischil

6.2.5 20は興味深い。私はそれがこの結果をもたらすことを意図していないと推測しますが、それは不完全なときに同じ型を持つ完全な型へのすべてのポインターが同じサイズでなければならないことを意味します。たとえば、の配列へのすべてのポインタintは互いに同じサイズでなければならず、特定の配列へのすべてのポインタstructは互いに同じサイズでstructなければなりませんが、異なる種類の配列へのすべてのポインタが同じサイズである必要はありませんお互いに。
エリックポストピシル

1
@EricPostpischilのテキストは、「同様に、互換性のある型の修飾されたバージョンまたは修飾されていないバージョンへのポインタは、同じ表現と配置の要件を持つ必要があります。」それらは互換性のあるタイプであり、修飾子を追加または削除できるためT(*)[]、と同じサイズでなければならないことを解釈する必要がありますT(*)[5]
MM

互換性のある型に異なるサイズを許可すると、多くの問題が発生します。標準で明示的に除外されていないのはおそらく欠陥です
MM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.