19

C99とC11の間の変更につながったメモを解読しようとしています。そのノートで提案された変更は、C11の6.2.4:8になりました。

構造体または共用体が配列型のメンバー(再帰的に、含まれるすべての構造体および共用体のメンバーを含む)を含む、構造体または共用体タイプの非左辺式は、自動保存期間と一時的な存続期間を持つオブジェクトを参照します。その存続期間は、式が評価されたときに始まり、その初期値は式の値です。含まれている完全な式または完全な宣言子の評価が終了すると、その存続期間は終了します。一時的な有効期間でオブジェクトを変更しようとすると、未定義の動作が発生します。

変更が必要な理由を理解しています(いくつかの議論はここにあります。議論はC11の前に戻っていることに注意してください)。しかし、私が理解していないのは、クラーク・ネルソンが彼のメモを書いたときに行った副次的な発言です。

このアプローチでは、C99で準拠していたこのような例が、非準拠であるとさらに宣言されていることに注意してください。

struct X { int a[5]; } f();
int *p = f().a;
printf("%p\n", p);

この例がC11で不適合である理由を理解しています。私が特に理解していないのは、C99でどのように準拠しているかです。そして、それがC99で定義されている場合、それは何をすることになっているのでしょうか、ダングリングポインタの値を明確に出力しますか?

4

1 に答える 1

8

私の理解では、C99では、オブジェクトの寿命の最も細かい部分はブロックです。したがって、6.5.2.2(および参照する注記で言及されている他の§)は、次のシーケンスポイント以降は戻り値にアクセスできないと具体的に述べていますが、技術的には、囲んでいるブロックを離れるまで、そのアドレスは不確定はありません。 (ただし、アクセスできないオブジェクト用にストレージを予約する必要がある理由は、読者の演習として残されています)。したがって、

struct X { int a[5]; } f();
int *p;
{ p = f().a; }
printf("%p\n", p);

C99およびC11では未定義です。C11では、C99には存在しない「一時的な存続期間」の概念により、完全な式が終了するとすぐにポインターが不確定になると見なすことができます。

于 2012-10-02T08:23:17.960 に答える