Search code examples
cgccc99compound-literals

How does compound literals work in this code?


I have the following code in which I wrote two functions. Both are meant to produce the same output. But the function g() which has loop produces a different output from what I had expected as shown below.

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

Output:

Calling function f()
0023ff20
0023ff24

Calling function g()
0023ff24
0023ff24

How come the address of p is same in case of g() when it was called?


Solution

  • Well, I don't know exactly what are you trying to accomplish, but what happens here is:

    • the (struct S){i} notation in C99 will create new data structure on stack
    • this data structure is automaticaly destroyed at the end of the scope in which it was created

    So in f() function you actually make TWO distinct structures in the scope of the whole function (even if you assign their addresses to the same pointer) - hence two different addresses.

    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
    

    But in g() function the p is created and destroyed in the inner block of the for block, and so it happens that p is allocated over and over again in the same position on stack, giving always the same address.

    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
    }