21

関連する質問:代入演算子がシーケンス ポイントでない正当な理由はありますか?

comp.lang.c FAQから、以下のプログラムは未定義であると推測できます。奇妙なことfに、引数の計算と への制御の転送の間のシーケンス ポイントとしてへの呼び出しのみが言及されていfます。fから呼び出し元の式への制御の転送は、シーケンス ポイントとしてリストされていません。

int f(void) { i++; return 42; }
i = f();

それは本当に未定義ですか?

多くの質問に追加する最後のメモとして、静的分析のコンテキストでこれに興味があります。私はこれを自分で書いているわけではありません。他の人が書いたプログラムで警告する必要があるかどうかを知りたいだけです。

4

2 に答える 2

9

f から呼び出し元の式に戻る制御の転送は、シーケンス ポイントとしてリストされていません。

はい、そうです。

完全な式の評価の最後に

 

式ステートメントを形成する完全な式、または if、switch、while、for、または do/while ステートメントの制御式の 1 つ、あるいは初期化子またはreturn ステートメント内の式。

return ステートメントがあるため、シーケンス ポイントがあります。

そのようにも見えません

int f(void) { return i++; } // sequence point here, so I guess we're good
i = f();

未定義です。(これは私にとってはちょっと奇妙です。)

于 2011-05-19T07:28:40.450 に答える
8

それはまったく未定義ではありません。C99 の付録 C にリストされているシーケンス ポイントの 1 つは完全な式の終わりであり、そのうちの 1 つは return ステートメントの式です。

return42 を返すので、そのステートメントの直後にシーケンス ポイントがあります。

完全を期すために、C99 シーケンス ポイントを以下に示します。関連するものは太字で示しています。

以下は、5.1.2.3 で説明されているシーケンス ポイントです。


  • 引数が評価された後の関数の呼び出し (6.5.2.2)。
  • 次の演算子の最初のオペランドの終わり: 論理 AND && (6.5.13); 論理和 || (6.5.14); 条件付き?(6.5.15); コンマ、(6.5.17)。
  • 完全な宣言子の終わり: 宣言子 (6.7.5);
  • 完全な式の終わり: 初期化子 (6.7.8); 式文中の式(6.8.3); 選択ステートメントの制御式 (if または switch) (6.8.4); while または do ステートメントの制御式 (6.8.5)。for ステートメントの各式 (6.8.5.3); return ステートメントの式 (6.8.6.4)
  • ライブラリ関数が戻る直前 (7.1.4)。
  • 各書式付き入出力関数変換指定子 (7.19.6、7.24.2) に関連付けられたアクションの後。
  • 比較関数の各呼び出しの直前と直後、および比較関数の呼び出しとその呼び出しに引数として渡されたオブジェクトの移動の間 (7.20.5)。
于 2011-05-19T07:25:03.567 に答える