9

重複の可能性:
これらの未定義の動作を誰かが説明できますか(i = i ++ + ++ i、i = i ++など…)

私のコードは次のとおりです。

#include <stdio.h>
int main()
{
  int x = 10, y = 0;
  x = x++;
  printf("x: %d\n", x);
  y = x++;
  printf("y: %d\n", y);
}

ポストインクリメントの性質を考えると、次の出力が期待されます。

x: 10
y: 10

私の推論は、5行x目で、増分が行われた後に初期値に割り当てる必要があるということです。

代わりに、しかし、私はこれを取得します:

x: 11
y: 11

アセンブリを掘り下げると、これは私には意図的な選択のように見えます。

LCFI2:
        movl    $10, -4(%rbp)   // this is x
        movl    $0, -8(%rbp)    // this is y
        incl    -4(%rbp)        // x is simply incremented
        movl    -4(%rbp), %esi
        leaq    LC0(%rip), %rdi
        movl    $0, %eax
        call    _printf
        movl    -4(%rbp), %eax  // now x is saved in a register,
        movl    %eax, -8(%rbp)  // copied to y,
        incl    -4(%rbp)        // and finally incremented
        movl    -8(%rbp), %esi
        leaq    LC1(%rip), %rdi
        movl    $0, %eax
        call    _printf

何が起きてる?GCCは私を自分から救おうとしていますか?私は便利な言語リファレンスを持っていませんが、これは意図されたセマンティクスを壊すと思いました。

4

4 に答える 4

13

には介在するシーケンス ポイントがないため、動作は未定義です。x = x++たとえば、C FAQを参照してください。

于 2010-07-19T02:25:49.093 に答える
4

post/pre-in/decrement が正確にいつ発生するかについて、C 言語では定義されていません。したがって、 などのステートメントx = x++は整形式ではありません - 避けてください。

于 2010-07-19T02:22:02.020 に答える
2

標準はさておき (これは標準に関して定義されていないため)、実行方法は私が期待していた方法です。

私の経験則では、 の行をx++に置き換えx++て、次の行 (またはプレインクリメントの前の行) にx置きます。x += 1

その経験則に従うと、コードは次のように記述されます。

#include <stdio.h>
int main()
{
  int x = 10, y = 0;
  x = x; // x: 10
  x += 1; // x: 11
  printf("x: %d\n", x);
  y = x; // y: 11
  x += 1; // x: 12
  printf("y: %d\n", y);
}
于 2010-07-19T02:42:13.030 に答える
1

あなたが持っているとき:

a = b++;

何が起こっているかというと、b が a に保存され、割り当てが完了した後、b が 1 ずつインクリメントされます。したがって、次のようにします。

x = x ++;

以前は x は 10 でしたが、10 が x に保存され、(printf が完了する前に) x が 1 ずつ 11 にインクリメントされます。そのため、11 が出力されます。

于 2010-07-19T02:23:40.847 に答える