Kami Kaze
Kami Kaze

Reputation: 2080

accessing the same member of different structs

Disclaimer: The following is trying to simplify the problem as much as possible. Originally the variable int x is a struct but I would figure that this is not important here.

Assume we have two structs in a union (I have no influence on this)

typedef struct a_t {
  int x;
  int irrelevant;
} a_;

typedef struct b_ {
  float also_irrelevant;
  int x;
} b_;

typedef union uni_t{
  a_ a;
  b_ b;
} uni;

Is it possible to access x in both structures by the same statement like ptr_to_struct->x? But afaik the pointer needs the correct type at compile time. So a dependend declaration similar to this Pseudocode

if (union contains a_)
{
  a_ * ptr_to_struct; // but outside of this scope
  ptr_to_struct = &(uni.a);
}
else 
{
  b_ * ptr_to_struct; // but outside of this scope
  ptr_to_struct = &(uni.b);
}

is impossible as far as I know.

Are there possibilties to get a "general" access to the variable x independent of the current state of the union?

Upvotes: 1

Views: 450

Answers (2)

John Zwinck
John Zwinck

Reputation: 249462

It is impossible. C does not have reflection, so the "name" x is not available at runtime. Nor do you have any data within the structs that indicates which type a given instance is (i.e. it's not a "tagged union").

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726899

You are correct, it is not possible. The type of ptr_to_struct is a secondary problem here. The primary problem is that the address of x inside uni changes based on which struct is "active" inside the union:

  • If a_ is "active", the offset of x from the top of the union is zero
  • If b_ is "active", the offset of x from the top of the union is sizeof(float) plus possible additional offset for field alignment

One solution to this problem would be to put x on the same spot in the initial sequence of fields in both structs:

typedef struct a_t {
  int x;
  int irrelevant;
} a_;

typedef struct b_t {
  int x; // Moved to the top
  float also_irrelevant;
} b_;

Now that x occupies the same position, C makes a guarantee that the address of x in the union is going to be the same if you access it through a.x or through b.x.

Upvotes: 1

Related Questions