0

++数値とポインターの演算子のC/C ++実装はどこにありますか?

私はウェブを見回しましたが、あまり見つかりませんでした...

4

4 に答える 4

6

実装は、コンパイラのソースコードにあります。

一般に、コンパイラは次のことを行います。

  • のタイプを推測しiます。
  • が単純な整数型または整数への参照である場合i、コンパイラは、メモリからのロード(必要な場合)と単純な+1増分を示す中間表現を生成します。
  • がポインタの場合i、コンパイラは、メモリからのロードを示す中間表現(必要な場合)の後sizeof(*i)に、+1の代わりに追加するadd命令を生成します。
  • iがオーバーロードされたスコープ内にあるタイプの場合、オーバーoperator++()ロードされた演算子定義への関数呼び出しを示す中間表現を生成します。

ここには魔法はありません。i++一般に、整数型の単純なadd命令incにマップされ、C++の関数呼び出しにマップされる可能性があります。

于 2013-01-05T06:09:43.957 に答える
4

私の答え(数について)はある程度まで役立つかもしれません:
あなたはポインターの答えを運転することができます

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=0i=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)
于 2013-01-05T06:13:24.910 に答える
3

この操作のために生成されたマシンコードを見たいと思います。ここ :

//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++

于 2013-01-05T06:10:48.480 に答える
1

これはかなり基本的な質問で、教科書から学ぶのが一番です。

とにかく

数字の場合

ビルトイン++は数値を1増やし、メモリの内容を変更します。この演算子は、整数オブジェクトと浮動小数点オブジェクトの両方で使用できます。そして、それを接頭辞演算子として、書くこと++xと、接尾辞演算子として書くことの両方として使うことができますx++

違いは、プレフィックスとポストフィックスのバリアントが生成する式の値です。プレフィックスは++xインクリメントxされ、の新しい値を生成しますx(C ++ではx、新しい値で、への参照を生成します)。接尾辞はx++増分し、の元の値をx生成します。x

ポインタ

接頭辞と接尾辞の違いは同じですが、「1ずつ増やす」の定義が異なります

T*Tの配列のi番目の項目を指すタイプのポインターの場合、そのポインターをインクリメントした後、配列のi+1番目の項目を指します。

これは、マシンコードレベルのアドレスが。だけ増加することを意味しsizeof(T)ます。

が整数p+nである式は、最終値が明確に定義されている場合、増分と同じ最終値を生成します。これは、と書くこともできます。nnn+p

于 2013-01-05T06:14:28.363 に答える