++
数値とポインターの演算子のC/C ++実装はどこにありますか?
私はウェブを見回しましたが、あまり見つかりませんでした...
実装は、コンパイラのソースコードにあります。
一般に、コンパイラは次のことを行います。
i
ます。i
、コンパイラは、メモリからのロード(必要な場合)と単純な+1増分を示す中間表現を生成します。i
、コンパイラは、メモリからのロードを示す中間表現(必要な場合)の後sizeof(*i)
に、+1の代わりに追加するadd命令を生成します。i
がオーバーロードされたスコープ内にあるタイプの場合、オーバーoperator++()
ロードされた演算子定義への関数呼び出しを示す中間表現を生成します。ここには魔法はありません。i++
一般に、整数型の単純なadd
命令inc
にマップされ、C++の関数呼び出しにマップされる可能性があります。
私の答え(数について)はある程度まで役立つかもしれません:
あなたはポインターの答えを運転することができます
i++
低レベルでどのように機能するか。int main(){
int i=0,j=0;
j=i++; // expresion includes two operations `+, =
printf("%d %d",j,i);
}
-S
あなたはフラグを使ってそれを分解することができますgcc (g++)
:
私のコードネームはm.c
$ gcc -S m.c
m.s
アセンブリファイルを作成します。
私が追加したコメントを読む:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl $1, 28(%esp) // i due to declarations
movl $0, 24(%esp) // j
movl 28(%esp), %eax // this two lines are j = i
movl %eax, 24(%esp)
addl $1, 28(%esp) // increment to i, i++
movl $.LC0, %eax
movl 28(%esp), %edx
movl %edx, 8(%esp)
movl 24(%esp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
このように割り当てが=
最初に行われ、次に++
。++
後置の 場合。
(私のコンパイラによると)
式の抽象構文木のボトムアップ評価j = i ++
。
ソースコード:
j = i++;
低レベルでは、2つの命令に分割されます(アセンブリコードで確認できます):
j = i i ++
どこi++
にありますかi = i + 1
// abstract syntax tree
+ (post)
/ \
/ \
= 1
/ \
/ \
j i
プレフィックスの場合++
(++ i):
j = ++i
また、式がその場合、抽象構文木を直接記述している と仮定します。
最初にインクリメントして++
から=
実行します。
// abstract syntax tree for j = ++i
=
/ \
/ \
j \
+ (prefix)
/ \
/ \
i 1
j = ++i
場所j=0
とi=1
最初 のアセンブリコード:
movl $1, 28(%esp) // i declaration
movl $0, 24(%esp) // j
addl $1, 28(%esp) // First Add 1 to i because i++ (before = perform)
movl 28(%esp), %eax // Below two steps: = performed j = i
movl %eax, 24(%esp)
この操作のために生成されたマシンコードを見たいと思います。ここ :
//sg
int main()
{
int i=0;
++i;
return 0;
}
コンパイル:gcc -S -fverbose-asm -masm=intel test.c
そしてここにアセンブリ(関連部分)があります:
mov DWORD PTR [ebp-4], 0 # i,
add DWORD PTR [ebp-4], 1 # i,
これをと比較してください
//sg
int main()
{
int i=0,j;
j=i+1;
return 0;
}
これはより長いasmを生成します:
mov DWORD PTR [ebp-4], 0 # i,
mov eax, DWORD PTR [ebp-4] # tmp62, i
add eax, 1 # tmp61,
mov DWORD PTR [ebp-8], eax # j, tmp61
また、最新のコンパイラは自動的i=i+1
に短いコンパイラに変更されることに注意してくださいi++
。
これはかなり基本的な質問で、教科書から学ぶのが一番です。
とにかく
ビルトイン++
は数値を1増やし、メモリの内容を変更します。この演算子は、整数オブジェクトと浮動小数点オブジェクトの両方で使用できます。そして、それを接頭辞演算子として、書くこと++x
と、接尾辞演算子として書くことの両方として使うことができますx++
。
違いは、プレフィックスとポストフィックスのバリアントが生成する式の値です。プレフィックスは++x
インクリメントx
され、の新しい値を生成しますx
(C ++ではx
、新しい値で、への参照を生成します)。接尾辞はx++
増分し、の元の値をx
生成します。x
接頭辞と接尾辞の違いは同じですが、「1ずつ増やす」の定義が異なります
T*
Tの配列のi番目の項目を指すタイプのポインターの場合、そのポインターをインクリメントした後、配列のi+1番目の項目を指します。
これは、マシンコードレベルのアドレスが。だけ増加することを意味しsizeof(T)
ます。
が整数p+n
である式は、最終値が明確に定義されている場合、増分と同じ最終値を生成します。これは、と書くこともできます。n
n
n+p