次のCコードが印刷されるのはなぜですか12 12 12
int main(int argc, char const *argv[]) {
int a = 2, *f1, *f2;
f1 = f2 = &a;
*f2 += *f2 += a += 2.5;
printf("%i %i %i\n", a, *f1, *f2);
return 0;
}
次のCコードが印刷されるのはなぜですか12 12 12
int main(int argc, char const *argv[]) {
int a = 2, *f1, *f2;
f1 = f2 = &a;
*f2 += *f2 += a += 2.5;
printf("%i %i %i\n", a, *f1, *f2);
return 0;
}
*f2 += *f2 += a += 2.5;
この行には未定義の動作*f2
があります。これは、シーケンス ポイントを介在させずに同じ式内で(つまりa
) の値を複数回変更したためです。UB は、プログラムが "Hello World" を出力したり、クラッシュしたり、出力し12 12 12
たり12 12 1029
、脳を食べ始めたりする可能性があることを意味します。未定義の動作に依存しないでください。
C++ 標準を引用するには (質問に C のタグが付けられていることは知っていますが、私には C 標準がなく、C でも同じルールが適用されることはわかっています)
特に明記されていない限り、個々の演算子のオペランドと個々の式の部分式の評価の順序、および副作用が発生する順序は規定されていません。式の評価によって最大 1 回。さらに、保存する値を決定するためにのみ、前の値にアクセスする必要があります。この段落の要件は、完全な式の部分式の許容される順序ごとに満たされるものとします。それ以外の場合、動作は未定義です。
int
1 つの変数のみを指しているため、すべてに対して同じ値が出力されます: a
。
(は) である12
ため出力され、それ自体に 2 回追加します。a + 2.5 = 4
a
int
@Downvoters: なぜそんなに否定的なのですか? 私の答えは、このコンパイラーがこのサンプルコードで何をしているのかを示していると思います。これは、OPが動作を理解するのに役立つはずです。私は、Armen Tsirunyanの答えが正しい (つまり、ティックを取得する必要がある) こと、および動作が標準に従って定義されていないことに同意します。しかし、標準は実装されており、コードをコンパイルし、実行時に突然手を上げてUndefined behaviour!
.
私は(整数)*f2
を*f1
指しているからです。a
そう*f2 = &a = 2
そして*f1 = &a = 2
この時点で、 の値に加算します2.5
(a
は整数であるため、 が得られます4
)。
あなたが持っているよりも
a = 4
f2 = 4
f1 = 4
この時点で、あなたはf2+f1+a = 12.