Home > database >  Using variable being initialized in a designated initializer
Using variable being initialized in a designated initializer

Time:10-28

Am I allowed to use a variable being initialized inside a designated initializer?

Consider the following listing:

struct A {
    int a;
    int * const a_ptr;
};

struct A foo(int a) {
    struct A result = {
        .a = a,
        .a_ptr = &result.a
    };

    return result;
}

demo

Am I allowed to use result in this designated initializer expression? Is this behavior defined? Is this code portable?

Update

My bad, the example contains a potential stack corruption. The listing should be:

struct A {
    int a;
    int * const a_ptr;
};

void foo(int a) {
    struct A result = {
        .a = a,
        .a_ptr = &result.a
    };

    bar(&result);
}

CodePudding user response:

The initialization by itself is fine.

At the time result is declared, its address (as well as the addresses of its fields) is constant. So it is safe to use &result.a in the initializer of result.

What is a problem however is that you're returning a copy of this structure. This copy contains the address of a local variable that no longer exists, so attempting to use the value of the a_ptr member of the returned struct will trigger undefined behavior.

CodePudding user response:

The question has changed completely, here is my new answer:

Your code is fine, you can check this, it won't assert on any platform.

You pass the pointer to the local variable result to bar. In bar that local variable still exists p points to that variable (result). Therefore the a_ptr still points to result.a.

But I'm just wondering what you're trying to achieve here.

#include <assert.h>

struct A {
  int a;
  int* const a_ptr;
};    

void bar(struct A *p)
{
  assert(p->a_ptr == &p->a);
}    

void foo(int a) {
  struct A result = {
      .a = a,
      .a_ptr = &result.a
  };

  bar(&result);
}

int main()
{
  foo(2);
}

BTW:

 struct A result = {
      .a = a,
      .a_ptr = &result.a
  };

is equivalent to this:

  struct A result;  
  result.a = a;
  result.a_ptr = &result.a;

but for latter you'd need to declare int* a_ptr; instead of int* const a_ptr;.

  • Related