1

我有以下代码,其中我编写了两个函数。两者都旨在产生相同的输出。但是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()

4

2 回答 2

5

好吧,我不确切知道您要完成什么,但这里发生的是:

  • C99中的(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
}
于 2012-12-13T17:48:18.907 回答
2

您应该检查汇编代码以确保,但我想,由于p在循环范围内本地分配了自动分配变量的地址(在堆栈上分配),它只是重用堆栈上的相同空间。

f()它不会这样做,因为两个结构在同一范围内共存,而在编译g()器中确定在第一次迭代结束时您将无法使用&((struct S) {0}).

只是出于好奇,-O2对 gcc4.2 进行了尝试,看看是否有任何变化:

Calling function f()
0x7fff5fbff388
0x7fff5fbff380

Calling function g()
0x7fff5fbff390
0x7fff5fbff390
于 2012-12-13T17:31:55.610 回答