我有以下代码,其中我编写了两个函数。两者都意味着产生相同的输出。但是具有循环的函数g()
产生的输出与我预期的不同,如下所示。
#include <stdio.h>
struct S { int i; };
void f(void)
{
struct S *p;
int i = 0;
p = &((struct S) {i});
printf("%p\n", p);
i++;
p = &((struct S) {i});
printf("%p\n", p);
}
void g(void)
{
struct S *p;
for (int i = 0; i < 2; i++)
{
p = &((struct S) {i});
printf("%p\n", p);
}
}
int main()
{
printf("Calling function f()\n");
f();
printf("\nCalling function g()\n");
g();
}
输出:
Calling function f()
0023ff20
0023ff24
Calling function g()
0023ff24
0023ff24
p
的地址如果g()
被称为{{1}},该怎么说?
答案 0 :(得分:5)
好吧,我不确切地知道你想要完成什么,但这里发生的是:
(struct S){i}
表示法将在堆栈上创建新的数据结构所以在f()
函数中,你实际上在整个函数的范围内创建了两个不同的结构(即使你将它们的地址分配给同一个指针) - 因此有两个不同的地址。
void f(void)
{
struct S *p;
int i = 0;
p = &((struct S) {i}); // <- first data structure, let's call it A
printf("%p\n", p); // <- address of the structure A printed
i++;
p = &((struct S) {i}); // <- second data structure, let's call it B
printf("%p\n", p); // <- address of the structure B printed
} // <- both A and B destroyed
但是在g()
函数中,p
在for
块的内部块中被创建和销毁,因此发生p在同一位置一次又一次地分配在堆栈上,总是给出相同的地址。
void g(void)
{
struct S *p;
for (int i = 0; i < 2; i++)
{
p = &((struct S) {i}); // <- data structure A created
printf("%p\n", p); // <- data structure A's address printed
} // <- data structure A destroyed
}
答案 1 :(得分:2)
您应该检查汇编代码以确定,但我想这是因为p
在循环范围内本地分配了自动分配变量的地址(在堆栈上分配),它只是重用了堆栈上的空间相同。
在f()
中它没有这样做,因为两个结构共存于同一范围内,而g()
编译器确保在第一次迭代结束时你将无法使用{ {1}}。
尝试使用gcc4.2上的&((struct S) {0})
来好奇,看看是否有任何变化:
-O2