5
y=x++;

CPUレベルや命令ではなく、最適化なしでコンパイラレベルで何ステップで壊れますか? x を y に割り当てるために一時的に作成されますか、それとも直接発生しますか?

4

6 に答える 6

15

C ++はas-ifの原則に従うため、答えは実際には「n」ステップです。

  • 2:1)に割り当てるxことができますy。2)インクリメントx
  • 使用しない場合は1になる可能性がありますy
  • 未定義の動作である可能性があり、次のようyに宣言されていますint& y = x;
  • 最終的に同じ結果が得られるのは、 100の割り当てと再割り当てである可能性があります。
于 2012-10-30T10:44:19.147 に答える
8
  1. 一時変数は値で作成されます== x
  2. x増分されます
  3. (その一時変数に保持されている)の古い値xがに割り当てられますy

これらが基本的な手順になります。

「プリミティブ」の意味によって異なります-CPU命令を意味する場合、答えは異なります。

後置および前置のインクリメント/デクリメント演算子についてもっと読みたいと思うかもしれません。

于 2012-10-30T10:41:01.653 に答える
2

プリミティブ ステップが何を意味するかによって異なります。プリミティブ ステップが CPU 命令である場合、以下のような簡単なテストを行いました。

(Linux 環境、g++ 4.6.3) g++ -S main.cpp を使用して、g++ によって生成される CPU 命令を表示すると、以下の出力が得られました。

movl -8(%ebp), %eax<br>
movl %eax, -4(%ebp)<br>
addl $1, -8(%ebp)

つまり、g++ は y を x にコピーしてから x を増やします。この場合、3 つの CPU 命令 (プリミティブ ステップと見なす場合) が生成されます。

コンパイラの最適化レベルと CPU アーキテクチャが異なると、結果が異なることに注意してください。

于 2012-10-30T11:09:07.133 に答える
2

これは、このコードをコンパイルするアーキテクチャによって異なります。

C++ は、これらのようなことを指定したり、可能な「プリミティブ ステップ」が何であるかさえ指定しません。

由緒あるM68000 CPUの考えられる答えの 1 つとして、次のようなものがあります。

move.l x, d0
addq.l #1, x
move.l d0, y

したがって、これは 3 つの命令 (プリミティブ ステップ) を使用し、レジスタの形式で 1 ​​つの一時的な命令を使用しますd0

注: M68k アセンブリを作成してからしばらく経ちましたが、上記のコードが有効であることを願っていますが、現在、関連する参照ページに到達する際に問題が発生しているようです。例として、私はそれが有効であると確信しています。

于 2012-10-30T10:40:41.480 に答える
1

演算子の優先順位表を参照してください

手順は次のとおりです。

  • の値が一時変数に割り当てられxます。

  • xが 1 増加します。

  • y一時変数値が割り当てられます。

つまり、抽象レベルでの 3 つの基本的なステップです。

于 2012-10-30T10:43:23.377 に答える
0
  • xのアドレスにレジスタを割り当てます
  • xのロードアドレス
  • xに一時レジスタを割り当てます
  • 間接参照x
  • yにレジスタを割り当てます
  • y<=xを割り当てます
  • 増分x
  • xを書き戻す
  • yのアドレスに一時レジスタを割り当てます
  • yのロードアドレス
  • yを保存します

次に、多くの最適化段階の後、おそらく2つの命令で処理されます。

add r0, r1, #0
add r1, r1, #1

コメントをありがとう-とにかく私のポイントは、コンパイラが変数を読み取るためだけにいくつかのステップを実行する必要があるかもしれないということでした。(グローバルまたはローカルスタックフレームにありますか、それともリンカーファイルによって指定された絶対アドレスを持っていますか...)

編集:もちろん、これで話は終わりではありません。xとyの変数はどのようなものですか?マシンレジスタ幅より長いですか?それらは短く、ゼロ拡張または符号拡張が必要ですか?たぶんそれらはfloatまたはdoubleであり、外部ライブラリへの呼び出しが必要です...

于 2012-10-30T10:44:08.673 に答える