理解指针(在C中):将int指针转换为char并更改值

时间:2017-02-24 21:22:57

标签: c pointers malloc

我有以下代码,它处理C

中的指针
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 [第一位将被覆盖,但这不会给出256]。我非常感谢帮助!在此先感谢:)

2 个答案:

答案 0 :(得分:2)

简短回答:您修改了c,因此它不再具有4字节整数对齐,并将其设置为500修改后的两个数组元素。此外,该未对齐访问通常是禁止的,并且将导致某些系统上的对齐错误。

答案很长:在第4步,a[1]包含0x00000190,即400,a[2]包含0x0000012D,即301.

让我们假设a[0]从内存地址0开始。这是字节在 little-endian 系统中的排列方式(这里的字节序非常重要),左边从0到15:到

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步,您通过演员阵营将c一个字节取消对齐char *,因此它指向地址05而不是04。您为其分配值500(0x000001F4),它将覆盖05-08中的字节,从而产生此内存:

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  

当您阅读a[1]时,您会得到0x0001F490,即128144 当您阅读a[2]时,您会得到0x00000100,这是256。

答案 1 :(得分:0)

要认识到的是这个

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

使c指向某些[1]和某些[2]。你将c移动一个字节,并使其成为一个int指针。这使* c地址为[1]的最后3个字节和[2]的第一个字节。抽出所有位,看看会发生什么