1

これに対する MS VC コンパイラの動作を理解するのに苦労しています。この行は正常にコンパイルされますが、得られる結果は私が期待するものとはまったく異なります。

this->Test((char *)&CS2 - (char *)&CS1 == sizeof(void *));

CS1 および CS2 引数は次のように宣言されます。

myFunction(tCS1* CS1, tCS2* CS2) {...

tCS1 と tCS2 は、それぞれ 1 つの int と 1 つの __int64 を含む構造体です。

これは、両方のポインターである引数 CS1 と CS2 の間のスタック上の距離を確認するためのものです。この行で実行を中断し、デバッガーを使用して 2 つの変数のアドレスを取得すると、実際には互いに 8 バイト離れていることがわかります (x64 プラットフォーム)。

ただし、比較の結果は false です。

コンパイラによって生成されたアセンブリ コードは次のとおりです。

mov         rax,qword ptr [CS1] 
mov         rdi,qword ptr [CS2] 
sub         rdi,rax 

(次に、rdi に格納された結果を使用して比較を行い、呼び出しを行います)

はい、コンパイラはアドレスではなく、ポインター引数の値を比較しています。ここには間接的なレベルがありません。どこに行ったのですか?

もちろん、これをテスト環境で再現することはできず、どこを見ればよいかわかりません。私は 32 ビット マシン上のこのコードを x64 プラットフォームにクロスコンパイルしています (そうしなければなりません)。それが唯一の「奇妙な」点です。アイデア、ヒントはありますか?

4

2 に答える 2

0

アセンブリ

mov         rax,qword ptr [CS1] 
mov         rdi,qword ptr [CS2] 
sub         rdi,rax

CS1 と CS2 が実際にはスタック引数ではなく、いくつかのグローバル シンボルであることを示します。同様の結果を生成したい場合は、次のようにします。

int* CS1 = NULL, *CS2 = NULL; /* or any other value...*/
#define CS1 *CS1
#define CS2 *CS2

もちろん、これは醜いコードですが、コードにそのようなものが含まれていないことを確認しましたか? また、動的リンカーがその役割を果たしている可能性があります。

最後になりましたが、次のようなコードを記述しようとすると:

void foo()
{
  int a;
  int b;
  printf("%d", &a-&b);
}

これは実際には未定義の動作であることに注意してください。C (および C++) では、単一のオブジェクト (配列など) 内を指すポインターの減算のみが許可されているためです。

于 2010-07-21T15:43:43.287 に答える
0

@jpalacekとコメンターが観察したように、これは未定義であり、コンパイラはそれを利用して好きなことをしている可能性があります。それはかなり奇妙です。

このコードは gcc で「動作」します。

#含む

int func(int *a, int *b)
{
    return (char *)&a - (char *) &b;
}

int main(void)
{
    int a、b;
    printf("%d", func(&a, &b));
    0 を返します。
}

(gdb) 逆アセンブル関数
関数 func のアセンブラ コードのダンプ:
   0x0 80483e4 : プッシュ %ebp
   0x080483e5 : mov %esp,%ebp
=> 0x080483e7 : lea 0x8(%ebp),%edx
   0x080483ea : レア 0xc(%ebp),%eax
   0x080483ed : mov %edx,%ecx
   0x080483ef : サブ %eax,%ecx
   0x080483f1 : mov %ecx,%eax
   0x080483f3 : ポップ %ebp
   0x080483f4 : 戻る    
アセンブラー・ダンプの終わり。

最適化により、相対アドレスを知っているだけです。

(編集:何らかの理由で回答がここで切り捨てられました)

(gdb) 逆アセンブル関数
関数 func のアセンブラ コードのダンプ:
   0x08048410 : %ebp をプッシュ
   0x08048411 : mov $0xfffffffc,%eax
   0x08048416 : ムーブ %esp,%ebp
   0x08048418 : ポップ %ebp
   0x08048419 : 戻る    
アセンブラー・ダンプの終わり。

興味深いことに、-O4最適化を使用すると +4 が返され、最適化を使用しないと -4 が返されます。

とにかくなぜこれをやろうとしているのですか?一般に、引数にメモリ アドレスがあるという保証はありません。引数はレジスタで渡される可能性があります。

于 2010-07-23T05:49:46.807 に答える