复合文字如何在此代码中工作?

时间:2012-12-13 17:27:51

标签: c gcc c99 compound-literals

我有以下代码,其中我编写了两个函数。两者都意味着产生相同的输出。但是具有循环的函数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}},该怎么说?

2 个答案:

答案 0 :(得分: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()函数中,pfor块的内部块中被创建和销毁,因此发生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