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

让我们从基础开始。

c是指向 s 数组的指针int

让它成为a

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

每两位数字是一个字节,我们假设sizeof(int)在我们的示例中是 4,​​因此其中的每个元素a都有 4 个字节,即 8 位数字。

现在,c是指向 中第一个元素的指针a

让我们看一下有问题的表达式:

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

显然,c这里发生了变化,但究竟发生了什么:

  1. cint*char*
  2. 强制转换的结果递增,结果sizeof(char)被添加到c. 因为sizeof(char)is 1,c增加 1 并指向 中元素的第二个字节a
  3. 结果被转换回int*,并重新分配给c。实际上不需要第二次演员表。

所以,忽略所有其他代码,我们从这里开始:

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

去这个:

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

正如丹尼尔在下面指出的那样,如果 c 没有正确对齐 type 的指针int*,则会出现未定义的行为,应该避免这种情况。

于 2013-02-01T15:43:26.303 回答
3

c是一个指向 int 的指针,所以通常c+1指的是sizeof(int)在内存中更远的地址——在 32 位系统上通常是 4 个字节。

但是您c转换为char*- 即指向字符的指针。现在,char只有 1 个字节长,所以(char *)c + 1指的是比;更远1 个字节的内存位置。c它位于at的中间intc

然后将结果转换回 aint*并将 500 写入其中。所以你正在做的是(可能)在最后 3 个a[1]字节和a[2]. 究竟会产生什么影响取决于系统的字节顺序,但这基本上就是正在发生的事情。

于 2013-02-01T15:39:01.283 回答