0

我正在做一些实验来看看 C 如何在堆栈上分配变量。以下代码出现了一些奇怪的行为。C 似乎正在向下增长堆栈,因此在以下示例中,字符 c 分配在紧接在 short s 之前的字节中。然后我创建一个 int 指针bigRandP并将其指向 c 占用的同一位置,因此它看到的“int”与 s 占用的堆栈空间重叠。然后我尝试为 int 指针引用的位置分配一些东西。

unsigned short nameSum = 0;
unsigned char smallRand = 0;
unsigned int* bigRandP;

//The "int" pointed to by iP should overlap s
bigRandP = (unsigned int*)(&smallRand);
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);
*bigRandP = 0;
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);

0028FF1A 0028FF19 0028FF19
0 0 419430400
0028FF1A 0028FF19 0028FF00
0 0 4210788

打印的结果很有趣。不仅分配失败(bigRandP 指向的 int 未设置为 0),而且 int 指针本身被静默地重新定位以指向堆栈下方的其他位置。到底是怎么回事?这是 C 编译器阻止我用重叠指针覆盖其他变量的方法吗?

4

1 回答 1

4

bigRandP是指向 的指针unsigned int

你把它指向一个unsigned char对象,然后你修改了指向的unsigned int对象。bigRandP

显然smallRand,并且bigRandP彼此靠近存储在内存中。通过尝试修改sizeof (unsigned int)1 字节对象的字节,您破坏了指针对象本身的一部分。

底线:您的程序的行为未定义。

此外,虽然这可能与您看到的行为无关,但%p格式需要一个void*参数。如果要打印其他类型的指针,应将其转换为void*

printf("%p %p %p\n", (void*)&nameSum, (void*)&smallRand, (void*)bigRandP);

在所有指针具有相同表示的系统上,无论是否使用强制转换,它都可能“工作”,但具有强制转换的版本在所有系统上都更正确。

于 2013-04-05T19:05:05.027 回答