Reputation: 83
The following code gives me a compiler error: left side of '.' or '->' is not struct or union
.
Sample code:
struct x {
u32_t y;
};
typedef struct x v1;
v1 xyz;
set_val(xyz, val);
Here I get the problem that xyz
is not an struct or union, but it is a struct or not?
#define set_val(xyz, val) ((xyz)->y= (val))
I've searched for this and found some people with the same problem, but don't understand how to fix it.
Upvotes: 0
Views: 1423
Reputation: 753645
The compiler message isn't great — it is combining multiple errors into a single message. Your macro invocation creates the text:
((xyz)->y= (val));
The trouble is, xyz
is a structure, and therefore you access members using xyz.y
and not xyz->y
. You could invoke:
set_val(&xyz, val);
and that would work OK; you pass a pointer and then dereference using the pointer notation. Or you could rewrite the macro as:
#define set_val(xyz, val) ((xyz).y = (val))
Note that the macro argument names xyz
and val
are only coincidentally the same as the arguments passed. I could write the macro as:
#define set_val(s, value) ((s).y = (value))
or
#define set_val(p, value) ((p)->y = (value))
(depending on which version you want to keep) and it would work the same way. The reusing of the same names could be adding to your confusion, though.
It might also be a good time to note that macros such as this are not necessarily a good idea because they can lead to confusion. You might do better with an inline function:
static inline void set_val(v1 *p, u32_t val) { p->y = val; }
Now at least you'll get a better error message if you call it the wrong way. Of course, the function must take a pointer to the structure — the function semantics still apply even to inline functions. It is still debatable whether the function is a benefit, but the type safety the function signature imposes is a big help.
Upvotes: 7