2

同級生が投稿したコードを見ていますが、この例のために単純化されています。

int main()
{
    int n = 0x4142;
    char * a = (char *) &n;

    char * b1 = (((char *) &n) + 1);
    char * b2 = (((int) &n) + 1);

    printf("B1 Points to 0x%x - B2 Points to 0x%x\n", b1, b2);

    printf("A Info - 0x%x - %c\n", a, *a);
    printf("B1 Info - 0x%x - %c\n", b1, *b1);
    printf("B2 Info - 0x%x - %c\n", b2, *b2);

   return 0;
}

出力は次のとおりです。

B1 Points to 0xcfefb03d - B2 Points to 0xcfefb03d
A Info - 0xcfefb03c - B
B1 Info - 0xcfefb03d - A
Segmentation fault (core dumped)

b2 を印刷しようとすると、セグメンテーション違反が発生します。出力には、セグフォルトの代わりに次の行を含める必要があると思います。

B2 Info - 0xcfefb03d - A

これはなぜですか?b1 と b2 は両方とも char* であり、両方とも同じアドレスを指しています。これは、sizeof(char*) == 8 および sizeof(int) == 4 の 64 ビット マシン上にあります。

4

3 に答える 3

3

しかし、64ビットコンピューターではセグメンテーションフォールトします

考えられる理由は、お使いのプラットフォームでは、ポインターが 64 ビットで、int が 32 ビットであることです。したがって、ポインターを にキャストするとint、情報が失われます。

私のコンパイラはこれについて特に警告します:

test.c:7:19: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

これは、次のプログラムを使用して簡単に確認できます。

#include <stdio.h>

int main()
{
   char *s = "";
   printf("%p %p\n", s, (char*)(int)s);
   return 0;
}

私のコンピューターでは、これにより 2 つの異なるアドレスが出力されます (2 番目のアドレスは上位ビットが切り捨てられています)。

私がよく理解していないのは、b1 と b2 の両方が char* であり、両方が同じアドレスを指していることです。

実際には、それらは同じアドレスを指していません。フォーマットprintf()指定子がすべて間違っています。最初printf()は次のようになります。

printf("B1 Points to %p - B2 Points to %p\n", b1, b2);

これを実行すると、アドレスが異なることがわかります。

于 2013-04-07T06:43:51.720 に答える
1

(int)&nポインタのサイズが int のサイズよりも長い場合 (64 ビット CPU ではよくあることです)、IOW にnあるビット数にのアドレスを切り詰める可能性があります。int安全に逆参照できません。

于 2013-04-07T06:45:19.140 に答える
1

あなたの例では、intは 4 バイトであるため、&nキャストして に代入しようとすると、 の値が切り捨てられますb2。ポインター値を整数として扱うuintptr_tには、プラットフォームの容量に関係なくポインターを安全に格納できる符号なし整数型を使用します。

char * b2 = (((int) &n) + 1);

次のようにする必要があります。

char * b2 = ((uintptr_t) &n) + 1;
于 2013-04-07T06:47:47.533 に答える