質問
C、このドピース:
int a;
a = 10 + 5 - 3
お願いしたいです:がある(10+5-3されている。(しか a
に位置しスタック、ウ (10+5-3)
?どのようなこrvalueくいただくことになります。)
解決
一般的に、R値は、プログラム自体の中に「格納される」。
つまり、コンパイラ自体(のプログラムは、これまでに実行される前にの)10 + 5を計算 - (それはすべて一定の即時値に基づいているのでので、それはそうすることができる)3値を、それは(この場合、コンパイラはおそらく種類のデータセグメントの原点に対する相対アドレスとして認識しているという名前の変数)assignementためにどのようなL値は、この計算の結果を格納するためにアセンブリコードを発します。
のアセンブリ命令内の12の値は、従ってだけプログラムのバイナリの中に発見されたr値を、
のように見えます mov <some dest, typically DS-relative>, $0C
$ 0Cは "r値" です。
r値のみ実行時に行うことができる演算の結果であることが起こった場合は、場合に、基礎となるCコードを言った:A = 17 * X。 // XいくつかのランタイムVAR、r値も「保存された」(またはむしろマテリアライズド)プログラムバイナリ内の一連の命令としてであろう。上記の単純な「MOV DEST、IMM」との違いは、それは、アキュムレータ内の変数xを読み込む17によって乗算し、変数aがアドレスに結果を格納するためにいくつかの命令を取ることです。コンパイラは、いくつかの中間結果などのスタックを使用するように;-)「そのものを許可する」ことが可能ですが、そのように
されるだろう
a)は完全にコンパイラに依存
B)transiant
C)と、一般的にのみ伴うだろう。の部分のr値の
の
r値は、プログラム(いないデータ)の部分にカプセル化され、コンパイル時の概念であり、どこが、プログラムバイナリに格納されていないと言うことは安全である。
paxdiabloに応じて:C標準が効果的にのないのような性質のものを指示しないため、上記の提供の説明は確かに可能性を制限するものです。あまり決して、ほとんどの任意のr値が最終的に実体化され、少なくとも部分的には、いくつかの(実行時に)計算するかどうか、適切な値となるようなものを設定した命令または即時により適切に対処されます。
他のヒント
定数は、おそらく、コンパイル時に単純化されています。コンパイラが好きどこでも、何かのように、たとえば、いくつかの変数から実行時に計算する必要がないi - j + k
は、CPUのアーキテクチャに応じて、「保存」することができる:コンパイラは、通常のレジスタを使用するために最善をしようとします、例えば
LOAD AX, i
SUB AX, j
ADD AX, k
はSTORE AX, dest
等であるメモリロケーションに割り当てる前に、アキュムレータレジスタAXにそれを「記憶」は、式を計算します。任意の合理的に簡単な式のためにメモリにレジスタをこぼさするために必要な
これは、コンパイラに依存します。通常値(12)は、コンパイラによって計算されます。次いで、これを、典型的には、ロード/即時アセンブリ命令を移動の一部として、コードに格納されます。
それはコンパイラまで、実際にの完全にはのある格納場所。標準では、この動作を規定していません。
A の典型的なの場所は、実際にコードをコンパイルしてアセンブラ出力を見ることによって見ることができます:
int main (int argc, char *argv[]) {
int a;
a = 10 + 5 - 3;
return 0;
}
生成する:
.file "qq.c"
.def ___main;
.scl 2;
.type 32;
.endef
.text
.globl _main
.def _main;
.scl 2;
.type 32;
.endef
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main
movl $12, -4(%ebp) ;*****
movl $0, %eax
leave
ret
該当ビットが;*****
にマークされ、あなたは値がコンパイラによって作成され、ちょうどmov
型命令に直接挿入されていることを見ることができます。
式が定数値であるので、それはこれだけシンプルだということに注意してください。すぐに(変数のような)非定数値を導入して、コードがもう少し複雑になります。あなたは、メモリ内のこれらの変数をルックアップする(または、彼らはすでにレジスタであってもよい)、その後に値を操作する必要があるためです。の実行時のではなく、のコンパイル時にの。
コンパイラは値がどうあるべきかを計算する方法としては、それは式の評価を行うことだと全体の他の質問です: - )
- 計算結果を、右軸(右側)が計算でコンパイラによりステップされている"一定の伝播".
- その後、格納されたとしてオペランドが議会の指導の価値
a
この分解からMSVC:
int a;
a = 10 + 5 - 3;
0041338E mov dword ptr [a],0Ch
あなたの質問が間違った前提に基づいています。
Cで左辺値の定義特性は、すなわち、それが 格納され、ストレージ内の場所を有することです。これは、の右辺値のから左辺値を区別するものです。右辺値は、のないの任意の場所に保存されています。つまり、右辺値にするものです。それは保存した場合、それは定義により、の左辺値のでしょう。
用語「左辺値」と「右辺値は」表現の世界を二分するために使用されています。それは、( - C ++でのルールはより複雑であるあなたがそれに&演算子を適用することができないため)(10+5-3)
は右辺値であることを起こる表現である、です。実行時には、何の表情、左辺値または右辺値はありません。特に、それらはどこにも保存されません。
あなたは不思議に思ったが、値12は左辺値でも右辺値(右辺値になりますが、あなたのプログラムに12
表示されない表現12
ではなく)もありません。