我有以下代码,它处理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]。我非常感谢帮助!在此先感谢:)
答案 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]的第一个字节。抽出所有位,看看会发生什么