void main(){
int i,k;
char* p;
int j;
printf("address of i is %d \naddress of k is %d \naddress of p is %p\naddress of j is %d", &i,&k,&p,&j);
}
当我尝试上述代码时,j的地址比k低4个单位。但是p的地址并不相近。由于指针是可以存储4个字节数据的整型变量,为什么它不像其他三个变量一样被分配在堆栈中呢?
void main(){
int i,k;
char* p;
int j;
printf("address of i is %d \naddress of k is %d \naddress of p is %p\naddress of j is %d", &i,&k,&p,&j);
}
使用 %p
来打印所有地址。
提示: 它确实在堆栈上。
(void *)
。到目前为止,所有代码示例都会调用_未定义的行为_,因为格式说明符与参数类型不匹配。虽然这可能没有太大的区别,但弹性的代码使用#include <stdio.h>
,int main(void)
和printf("%p\n", (void *)&p);
等。 - Jens你应该发布你正在获取的输出结果。我怀疑你感到有点困惑,因为你打印的大多数地址都是用十进制(使用%d)显示,而p
是用十六进制(使用%p)显示的。
我刚刚在我的电脑上(运行Ubuntu 9.04)尝试了你的代码,结果如下:
address of i is 0xbf96fe30
address of k is 0xbf96fe2c
address of p is 0xbf96fe28
address of j is 0xbf96fe24
在对代码进行一些更改后:
void main(){
int i,k;
char* p;
int j;
printf("address of i is %p \naddress of k is %p \naddress of p is %p\naddress of j is %p\n", &i,&k,&p,&j);
}
由于你所有的printf()都是地址,所以应该使用%p而不是%d。也许你误解了你的结果?
我不得不告诉你,你的程序是那些“应该缩进六英尺并覆盖泥土”的程序之一。(谷歌一下是谁说的,为什么说的:-) 它是懒散的一个典型例子,原因如下,其中大部分都会导致未定义的行为:
正确编写的代码应该像这样:
#include <stdio.h>
int main (void)
{
int i, k;
char *p;
int j;
printf ("address of i is %p\n", (void *)&i);
printf ("address of k is %p\n", (void *)&k);
printf ("address of p is %p\n", (void *)&p);
printf ("address of j is %p\n", (void *)&j);
return 0;
}
%d
printf()
说明符时,你会得到一个以十进制数打印的地址,而当你使用%p
说明符时,你会得到一个以十六进制数打印的地址。恰好这个十六进制数不包含字母,所以你误解了它。最终,指针是一个变量。就Linux架构而言,很明显所有那些内存局限于函数的变量将会留在堆栈中。
对于上述情况,指针为什么不能在堆栈中呢?这是一种误解输出并忽略gcc警告的情况。初学者们常常忽视gcc警告,认为它们是无害的。但有时候它们等同于编译器错误。
指针可能位于堆栈上,也可能不位于堆栈上,因为它们也是某种类型的变量。请注意,它们是一些不是很大的变量。如果 CPU/MCU 有很多寄存器并且编译器进行了良好的优化,您可能看不到指针在堆栈上,它可能会在寄存器中度过其整个生命周期。