Reputation: 41
I was looking at a pic 10 include file (p32mk1024gpk064.h) and was wondering why they added a struct with a single element instead of an union between a struct and an uint_32.
typedef union {
struct {
uint32_t RB0:1;
uint32_t RB1:1;
uint32_t RB2:1;
uint32_t RB3:1;
uint32_t RB4:1;
uint32_t RB5:1;
uint32_t RB6:1;
uint32_t RB7:1;
uint32_t RB8:1;
uint32_t RB9:1;
uint32_t RB10:1;
uint32_t RB11:1;
uint32_t RB12:1;
uint32_t RB13:1;
uint32_t RB14:1;
uint32_t RB15:1;
};
struct {
uint32_t w:32;
};
} __PORTBbits_t;
VS
typedef union {
struct {
uint32_t RB0:1;
uint32_t RB1:1;
uint32_t RB2:1;
uint32_t RB3:1;
uint32_t RB4:1;
uint32_t RB5:1;
uint32_t RB6:1;
uint32_t RB7:1;
uint32_t RB8:1;
uint32_t RB9:1;
uint32_t RB10:1;
uint32_t RB11:1;
uint32_t RB12:1;
uint32_t RB13:1;
uint32_t RB14:1;
uint32_t RB15:1;
};
uint32_t w:32;
} __PORTBbits_t;
I tried compiling both version and they both work, Idk what's the point of the second struct
Upvotes: 2
Views: 81
Reputation: 4317
In the before time (before C11), neither of these data types would have been valid. Every field in a structure or union would need a name. If we take your first example, and cut it down to a single bit in the first struct, you'd have:
typedef union {
struct {
uint32_t RB0:1;
};
struct {
uint32_t w:32;
};
} __PORTBbits_t;
Neither of the two struct
s are given a name, and this would be invalid. You'd need to have something like:
typedef union {
struct {
uint32_t RB0:1;
} bits;
struct {
uint32_t w:32;
} word;
} __PORTBbits_t;
and you'd access those like:
__PORTBbits_t foo;
uint32_t bar = foo.word.w; // Ignore all the UB for uninitialised variables
uint32_t bit = foo.bits.RB0;
C11 allows anonymous structs, so long as the fields are all unique. This lets you skip naming internal structures. In that case, both of your examples would be valid, and you could access them like:
__PORTBbits_t foo;
uint32_t bar = foo.w;
uint32_t baz = foo.RB0;
Your second example both uses and does not use this feature. Cropped as before you have:
typedef union {
struct {
uint32_t RB0:1;
};
uint32_t w:32;
} __PORTBbits_t;
Here, we have RB0
used as part of an anonymous structure, but w
as an explicitly named field (not in an anonymous structure).
Both examples use the C11 syntax though, there is no reason to prefer one over the other, they behave exactly the same. The first example is at least consistent and symmetrical regarding the structure fields.
TL/DR; Both versions are exactly the same, in practice. There may be stylistic (or company policy) reasons to prefer one over the other, but the generated code will be the same.
Upvotes: 2