0

次のプログラムに入力として 4 つの整数 (a = 10、b = 20、d = 30、e = 40 など) を指定すると、 と が計算さc = a + b = 0f = d + e = 70ます。この異常な動作は、短い int に間違った書式指定子を使用しているためであることはわかっていますが、ここで正確に何が起こっているのでしょうか? 最後の 2 つの入力の合計が正しく、最初の 2 つの数値の合計が常に 0 になるのはなぜですか?

#include<stdio.h>

void main()
{
    short int a, b, c, d, e, f;
    scanf("%d%d%d%d", &a, &b, &e, &d);
    c = a + b;
    f = d + e;
    printf("%d\n%d\n", c, f);
}
4

3 に答える 3

3

これは未定義の動作であるため、実装を詳細に分析せずに「理由」を示すことはできません。しかし、ほとんどの場合、コンパイラが選択した変数のレイアウトが原因で、他の変数を読み取るときに一部の変数が破壊されました。

私のコンパイラでは、のアドレスを出力する行を追加した後a, b, d, e、出力が得られました

0
70
0x7fffa94d30ca
0x7fffa94d30c8
0x7fffa94d30c6
0x7fffa94d30c4

何が起こったのかはおそらく¹

  1. aの下位バイトに格納された 10へのスキャン0x7fffa94d30ca、次の 3 バイト (リトル エンディアン マシン) の 0 に格納され、変数のいずれにも割り当てられなかったスタックの 2 バイトを上書きしますが、残念ながら致命的な結果はありません。
  2. bのバイトに格納されている 20へのスキャン0x7fffa94d30c8、0 を次の 3 バイトにスキャンし、に割り当てられた 2 バイトを上書きするため、 0 にa設定します。a
  3. e(アルファベット順および宣言順から巧妙に実行された) スキャンインは、30 を0x7fffa94d30c4次の 3 バイトに格納し、最後の 2 バイトdは割り当てられた場所に格納されましたがd、後でスキャン インされるため、
  4. d次の 3 バイトに格納されている 40と次の 3 バイトに 0 をスキャンし0x7fffa94d30c6、0 で上書きbします。
  5. c = a + b他の変数へのスキャン時に両方の変数が上書きされたため、加算の結果は 0 になり、スキャン後にとf = d + eのどちらも上書きされなかったため、加算の結果は 70 になります。de

スタックに強制的cに割り当てられ、そのアドレスを出力してレジスタに配置されていないため、ここではスキャンが代わりにd上書きされ、それに応じて加算が20になりました。cbc = a + b

¹フォーマット指定子short intを使用して変数にスキャンすることは未定義の動作であるため%d、何かが起こる可能性がありますが、コンパイラが UB を悪用するために道を外れなければ、簡単な説明が正しいものになります。

于 2012-07-03T19:01:28.903 に答える
3

"%d"を読み取るために使用される形式コードですintshortが より小さい場合、int"%hd"を読み取るための適切な形式コードですshort int

于 2012-07-03T19:12:58.760 に答える
1

何が起こっているかというと、「%d」は入力から数値を読み取って解析し、それを int に変換し、その int を対応するアドレスに格納するように scanf に指示します。通常、int は 32 ビット (4 バイト)、short int は 16 ビット (2 バイト) ですが、これは異なる場合があります。

scanf は「%d」ごとに 4 バイトを書き込みますが、&a、&b、&e、および &d のそれぞれに 2 バイトしか渡しませんでした。したがって、2 バイトは正しいアドレスに移動し、残りの 2 バイトは &a、&b、&e、および &d の隣にあるものに移動します。それらのいくつかは互いに隣り合っており、漂遊バイトによって上書きされます。

明らかに、これは非常に壊れたコードであり、決して使用しないでください。どの変数がメモリ内でどの変数の隣にあるかを当てにすることはできません。

于 2012-07-03T20:25:38.553 に答える