为什么指针不会存储在堆栈中?

3
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个字节数据的整型变量,为什么它不像其他三个变量一样被分配在堆栈中呢?

1
一些规范注释:
  • main() 函数应该返回一个整型
  • 当使用 printf() 函数时,始终确保在末尾加上 '\n'。
- eyalm
7个回答

13

使用 %p 来打印所有地址。

提示: 它确实在堆栈上。


1
请注意,您必须将%p的每个参数强制转换为(void *)。到目前为止,所有代码示例都会调用_未定义的行为_,因为格式说明符与参数类型不匹配。虽然这可能没有太大的区别,但弹性的代码使用#include <stdio.h>int main(void)printf("%p\n", (void *)&p);等。 - Jens

12

你应该发布你正在获取的输出结果。我怀疑你感到有点困惑,因为你打印的大多数地址都是用十进制(使用%d)显示,而p是用十六进制(使用%p)显示的。


6

我刚刚在我的电脑上(运行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。也许你误解了你的结果?


0

我不得不告诉你,你的程序是那些“应该缩进六英尺并覆盖泥土”的程序之一。(谷歌一下是谁说的,为什么说的:-) 它是懒散的一个典型例子,原因如下,其中大部分都会导致未定义的行为:

  • 使用printf而没有包含stdio.h
  • 使用void main
  • 使用%d来表示地址
  • 使用%p与指向void以外的其他内容

正确编写的代码应该像这样:

#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;
}

0
当你使用%d printf()说明符时,你会得到一个以十进制数打印的地址,而当你使用%p说明符时,你会得到一个以十六进制数打印的地址。恰好这个十六进制数不包含字母,所以你误解了它。

0

最终,指针是一个变量。就Linux架构而言,很明显所有那些内存局限于函数的变量将会留在堆栈中。

对于上述情况,指针为什么不能在堆栈中呢?这是一种误解输出并忽略gcc警告的情况。初学者们常常忽视gcc警告,认为它们是无害的。但有时候它们等同于编译器错误。


-1

指针可能位于堆栈上,也可能不位于堆栈上,因为它们也是某种类型的变量。请注意,它们是一些不是很大的变量。如果 CPU/MCU 有很多寄存器并且编译器进行了良好的优化,您可能看不到指针在堆栈上,它可能会在寄存器中度过其整个生命周期。


2
在 OP 的情况下,编译器无法优化指针变量,因为代码期望获取变量的内存地址(&p),这对于寄存器来说是无效的。 - Frank Bollack
@Frank:我指的是问题(标题本身),而不是给出的代码片段... - Malkocoglu
详细阐述问题是罪过吗 :-) - Malkocoglu
@Malkocoglu:不是的,但你应该明确表示,你的回答并没有涉及到原帖提出的实际问题。同时,你也应该考虑到,你的回答可能会让原帖作者在寻找解决方案时走向错误的方向。 - Frank Bollack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接