2016-07-27 4 views
-2

ISO/IEC 9899(TC2)§6.5 - 2式が教えてくれる:なぜprintf( "%d%d%d"、++ i、i、i ++)は未定義の動作ですか?

以前と次のシーケンスポイント間でオブジェクトが格納された値は、式の評価によって、最高1回に変更なければなりません。さらに、以前の値は、格納される値を決定するためにのみ読み出されるものとする。

これは私が心に留めていたことであり、タイトルからの行が予期せぬ出力を与える理由を誰にも尋ねたと思います。

は、しかし、今日、私はちょうどこのライン発見:

§7.19.6 - 1書式付き入力/出力機能:

をシーケンスポイントの後があるかのようにフォーマットされた入力/出力機能を振る舞うもの各指定子に関連付けられたアクション。

私が想定し作られたどの:

int i = 0; 
printf ("%d, %d", ++i, i++); 

は未定義である必要がありますが、次の例では、言及した句で[OK]をする必要があり:

int i = 0; 
printf ("%d, %d, %d", ++i, i, i++); 

しかし、出力は次のようになります。

2, 2, 0 

これは未定義の動作を示す良い例ではありませんでした。

なぜですか? 句がtrueの場合

「[...]各指定子に関連付けられたアクションの後にシーケンスポイントがあるかのように振る舞います。」

(関連配列点を表すSP)

: - 次に§6.5下ルール適用

指定子に関連付けられたactiosnの各々に2は、私たちは同様にそのルールを交差させません

SP ++i SP i SP i++

前のSPと次のSPの間の指定された範囲のSP1から、++iiの格納値の唯一の変更です。

SP2からは、前のSPと次のSPの間の範囲は、++iiです。++iは、この値の唯一の変更です。私たちは今、SP3を取る場合

前のSP(SP2)、次のSP(呼び出しの終わり)との間で起こっていることすべてがある:

i、全体でii++まだ1つだけ修正前のSPと次のSPの間の範囲。

ここで私はシーケンスポイントの仕方について間違って解釈していますか?

+0

あなたがそれが適切であると思うならば、それを下降させてください。しかし、これは単なる別の問題ではないことに注意してください。私は私には奇妙に見える何かに遭遇した、私はそれについてのまともな研究を静かにし、私の混乱の明確なポイントを作った、なぜこれは他の質問とは異なるです。あなたがまだ何かを見逃していると思ったり、十分な努力をしなかったと思ったら、どうしてそう思うかを少なくとも私に教えてください。 – dhein

答えて

1

問題は、指定子に関連付けられたアクションでは発生しません。問題は、printf関数へのパラメータの計算であり、最初の指定子がアクションを実行する前に終了しています。

ここ
void foo (int i1, int i2, int i3) 
{ 
    printf("%d, %d, %d", i1, i2, i2); 
} 

foo (++i, i, i++); 

、それは非常に明確になります:

はコードであった場合を想像してみてください。そしてラッパーは何も変わらない。

+0

アソシエートされたアクション間のそれらのシーケンスポイントが、それに当てはまる場合にも関連するケースについて詳しく説明できますか?それとも私はそれを別個の質問として尋ねるべきですか? – dhein

+0

'scanf'のようなことは明らかです。 'printf'で異なったフォーマット指定子があるかもしれませんが、私は考えることはできません。多分誰かができる。 –

+2

具体的には、指定されたアドレスに今までに出力された文字数を書き込むフォーマット指定子 '%n'です。 –

関連する問題