0

これがコードです。4回目の印刷までは簡単にたどりましたが、5回目の印刷ではわかりません

なぜ"5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302 "ですか?

理解できないコードの行にコメントしました。あなたのお返事をお待ちしてます。

"#include <stdio.h>
#include <stdlib.h>

void
f(void)
{
    int a[4];
    int *b = malloc(16);
    int *c = 0;
    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]);

    //I DONT UNDERSTAND WHAT THIS LINE BELOW DOES
    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;
}



output:
1: a = 0x7fff65fdcb90, b = 0x1065007e0, c = 0x0
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 = 0x7fff65fdcb90, b = 0x7fff65fdcb94, c = 0x7fff65fdcb91
4

2 に答える 2

8

基本から始めましょう。

cs の配列へのポインタintです。

これを次のようにしますa

[00000000][00000000][00000000][00000000]

2 桁ごとに 1 バイトであり、この例では 4 であると想定しているsizeof(int)ため、 のすべての要素aは 4 バイト、つまり 8 桁になります。

現在、cは の最初の要素へのポインタaです。

問題の式を見てみましょう。

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

明らかに、cここで変更されていますが、正確には次のようになります。

  1. cからにキャストさint*れますchar*
  2. キャストの結果がインクリメントされ、sizeof(char)に追加されcます。sizeof(char)is1であるため、 は 1 ずつインクリメントされ、 の要素の2 番目のバイトcを指します。a
  3. 結果は にキャストバックされint*、 に再割り当てされcます。この 2 番目のキャストは、実際には必要ありません。

したがって、他のすべてのコードを無視して、次から始めます。

a : [00000000][00000000]...
     ^
  c -|

そしてこれに行きます:

a : [00000000][00000000]...
       ^
  c ---|

Daniel が以下で指摘したように、 c が type のポインターに対して正しくアラインされていない場合int*未定義の動作が発生するため、これは回避する必要があります。

于 2013-02-01T15:43:26.303 に答える
3

cは int へのポインタであるため、通常c+1はメモリ内のさらに先のアドレスを参照しますsizeof(int)。通常、32 ビット システムでは 4 バイトです。

しかし、あなたはキャストcしますchar*- つまり、文字へのポインタです。現在、charは 1 バイトの長さしかないため、 より1 バイト(char *)c + 1先のメモリ位置を参照します。atの真ん中にあります。cintc

次に、結果を an にキャストし、int*500 を書き込みます。つまり、(おそらく) の最後の 3 バイトa[1]a[2]. 正確にどのような効果があるかは、システムのエンディアンによって異なりますが、基本的にはそれが起こっています。

于 2013-02-01T15:39:01.283 に答える