1

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?

Kami Kaze
  • 2,069
  • 15
  • 27
  • 4
    Looks like [XY](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) problem. – freestyle Mar 28 '18 at 11:55
  • 1
    You can just get pointer to the `x` field. – freestyle Mar 28 '18 at 11:56
  • @freestyle A pointer to `x` is exactly what I want to avoid. Because as this is a simplification, I have quite more variables like `x`so then I would need a pointer to each element. – Kami Kaze Mar 28 '18 at 12:01
  • Then, probably you will not get a good answer, since you did not accurately describe your problem. – freestyle Mar 28 '18 at 12:05
  • XY problem. Use an outer `struct` for the common filds and a `union`or the different ones. – too honest for this site Mar 28 '18 at 13:07
  • @Olaf sadly this is impossible as I have no influence on the definition of the structs and unions. – Kami Kaze Mar 28 '18 at 13:13
  • @KamiKaze: Then you're lost. Either have that fixed or get rid of that software. Or you still could have an XY problem. State what you **want** to do, not **how**. Strangely you accepted the answer which exactly recomends to change the structures, which you now claim you can't. – too honest for this site Mar 28 '18 at 13:26
  • @Olaf I am not entirely lost :). this would just have been a more elegant solution to a problem that arrises in an"IDE" we use for programming special devices. It kinda supports c for the programmer (together with structered text and FBD). But limits the use of certain features natural to c and also has quite a lot of code generated in the background. So for you to understand the whole problem I would have to write multiple pages of explanation or you would have to know this (quite exotic) tool by yourself. The answers I got are sufficient to know that I have to do it the uglier way. – Kami Kaze Mar 28 '18 at 13:33
  • Sidenote: any reason you use `static` pointers in your function? And why do you think getting a pointer to each `struct` is impossible? Sorry, but it looks like you are in urgent need of a good C book. – too honest for this site Mar 28 '18 at 13:35
  • If it is not C, don't use the C tag! Read the tag-wiki to see what the tag implies (and read the standard to see what the language is). I know such tools well enough to avoid them like hell. What you state is just the tip of the iceberg of the problems they cause. There never is a reason to use a tool which generates invalid/problematic code and imposes such restrictions. – too honest for this site Mar 28 '18 at 13:36
  • @Olaf as I wrote this is Pseudocode. it is not meant to be used this way. The static should just get the pointer out of the scope of the if/else. I did not state that a pointer to a struct is impossible. I stated that I assume it is impossible to get a variable with context dependent type in c. Before infering a lack of knowledge on my part, please read the (allready answered) question more thoroughly. Also this question is just about C. I was hoping for a way to handle unions I didn't know of. That I have no influence on some parts of the code is not uncommon and doesn't make it non-C – Kami Kaze Mar 28 '18 at 13:52
  • "The static should just get the pointer out of the scope of the if/else" - `static` has nothing to do with scope. As I wrote: C book! – too honest for this site Mar 28 '18 at 13:53
  • @Olaf Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/167737/discussion-between-kami-kaze-and-olaf). – Kami Kaze Mar 28 '18 at 13:57

2 Answers2

1

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.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks for the confirmation of what I thought. I have no influence on the order in those struct as they get generated at (right before) compile time. – Kami Kaze Mar 28 '18 at 12:06
1

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").

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Information about the type of the union is available, but not directly in the union. – Kami Kaze Mar 28 '18 at 12:02
  • @KamiKaze: Then you can write a function which takes in the union and the type information and returns x. But of course you'll need one such function for each variable you want to access. – John Zwinck Mar 28 '18 at 12:16
  • That is basically what I have right now,but it seems clumsy, hence I asked for another solution. Thank you – Kami Kaze Mar 28 '18 at 12:20