2017-02-24 3 views
1

私はC理解ポインタ(Cで):charにint型のポインタを変換して変化する値

内のポインタ
void 
f(void) 
{ 
    int a[4]; 
    int *b = malloc(16); 
    int *c; 
    int i; 

    printf("1: a = %p, b = %p, c = %p\n", a, b, c); 

    c = a; 
    for (i = 0; i < 4; i++) 
     a[i] = 100 + i; 

    c[0] = 200; 
    printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    c[1] = 300; 
    *(c + 2) = 301; 
    3[c] = 302; 
    printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    c = c + 1; 
    *c = 400; 
    printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    c = (int *) ((char *) c + 1); 

    *c = 500; 
    printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    b = (int *) a + 1; 
    c = (int *) ((char *) a + 1); 
    printf("6: a = %p, b = %p, c = %p\n", a, b, c); 
} 

int 
main(int ac, char **av) 
{ 
    f(); 
    return 0; 
} 

出力を扱う次のコードを、持っている:

1: a = 0x7fff5fbff710, b = 0x1003002e0, c = 0x100000000 
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103 
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302 
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302 
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302 
6: a = 0x7fff5fbff710, b = 0x7fff5fbff714, c = 0x7fff5fbff711 
Program ended with exit code: 0 

を、私は理由を理解[1]は128144です(私たちはintポインタをchar +1にキャストして500を上書きするとバイトを前に移動しています)、なぜ[2]が256であるのか分かりません[最初のビットは-written、しかしそれは256を与えません]。私は非常に助けを感謝します!事前に感謝:)

+0

ここで問題が発生しているわけではありませんが、厳密なエイリアシングルールとアライメントされていないメモリアクセスについてお読みください。 – bace1000

答えて

0

実現する事は、この

c = (int *) ((char *) c + 1); 

は、[2]の[1]といくつかのいくつかのCポイントになるということです。あなたはcバイトを1バイト移動させて、それをintポインタにします。これにより、* cは[1]の最後の3バイトと[2]の最初のバイトに対応します。すべてのビットを引き出し、何が起こるかを確認してください。

+0

私は[1] = 128144 )。 しかし、[2]が256にならない場合は、最後に試してみることができますか? (私はそれが私の終わりのように見えるものの画像を投稿することができます - 助けがあれば教えてください) –

+0

これはおそらく未定義の動作です。 – Barmar

+0

アンドリューは私たちのために重い持ち上げをして、これがどうなったかをあなたに示しました、私はあなたのためのエクササイズとして残しました – pm100

2

短い答え:cを修正しました。これで4バイトの整数整列がなくなり、500の2つの配列要素が変更されました。また、アライメントされていないアクセスは一般的にno-noであり、一部のシステムではアラインメントフォルトが発生します。

長い答え:ステップ4で、a[1]が400である0x00000190が含まれており、a[2]は301

ある0x0000012Dはのは、ここではメモリアドレス0でa[0]開始を想定してみましょう含まれているバイトが少し内に配置されている方法です

ADDR: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
DATA: C8 00 00 00 90 01 00 00 2D 01 00 00 2E 01 00 00 

ステップ5で、あなたはそれので、char *にあなたのキャストを経由して1バイトでc非整列しました:-endianシステムは、左から右に0から15(エンディアンがここに非常に重要です) 〜を指すddress 05の代わりに04です。あなたは値を割り当てる500このメモリで、その結果、5月8日からバイトを上書きすることに(0x000001F4):あなたがa[2]を読んだとき、あなたが0x0001F490 128144.
され得るあなたがa[1]を読んだとき

ADDR: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
DATA: C8 00 00 00 90 F4 01 00 00 01 00 00 2E 01 00 00 

0x00000100 = 256を取得してください。

関連する問題