I'm trying to initialize a struct which has a union inside and am not sure how to do it correctly. The code is part of a bigger GitHub Repository, so I don't want to change the initial code. Here's the Struct :
typedef struct SYP_encoder_stru {
char name[15];
u8 type;
s16 val_min;
s16 val_max;
s16 value;
u8 step;
u8 miditype;
union {
u8 midicc;
u16 midirpn;
u16 midinrpn;
};
u8 mapping;
u16 wordstart;
u16 ebpos;
} SYP_encoder_struct;
If I want to create an Encoder Struct in another file, would this be right?:
SYP_encoder_struct enc1 = {
"OSC1 Shape", //name
0, //type
0, //val min
127, //val max
0, //value
1, //stepping
0, //miditype
20, //midicc?? what about midirpn and midinrpn
0, //mapping
0, //wordstart
0 //ebpos
};
I'm just not sure because of the Union. Is this how to initiliaze a struct if it has an union inside? What if I want to initiliaze midirpn or midinrpn instead of midicc?
P.S.: The Code is written in C, sorry forgot to mention.
CodePudding user response:
The union in the struct should given a variable name, such as "union_v":
typedef struct SYP_encoder_stru {
char name[15];
u8 type;
s16 val_min;
s16 val_max;
s16 value;
u8 step;
u8 miditype;
union {
u8 midicc;
u16 midirpn;
u16 midinrpn;
} union_v;
u8 mapping;
u16 wordstart;
u16 ebpos;
} SYP_encoder_struct;
And you should set the member using the designated initializer format ".member = value
" one by one, and set the union variable directly such as ".union_v.midicc = 20
" for midicc
, or ".union_v.midirpn
" for midirpn
.
SYP_encoder_struct enc1 = {
.name = "OSC1 Shape", // name
.type = 0, // type
.val_min = 0, // val min
.val_max = 127, // val max
.value = 0, // value
.step = 1, // stepping
.miditype = 0, // miditype
.union_v.midicc = 20, // midicc?? what about midirpn and midinrpn
.mapping = 0, // mapping
.wordstart = 0, // wordstart
.ebpos = 0 // ebpos
};
CodePudding user response:
The correct way to initialize a struct like this depends on the newest version of C that your compiler can handle.
The example you gave is perfectly valid, and is called a designated initializer.
If your compiler can handle C99 or newer, then you can use compound literals like this:
SYP_encoder_struct enc1 = (SYP_encoder_struct){
.name = "OSC1 Shape", .type = 0, .val_min = 0, .val_max = 127, .value = 0,
.stepping = 1, .miditype = 0, .midicc = 20, .mapping = 0, .wordstart = 0,
.ebpos = 0 };
Alternatively, you can individually assign to each element in the struct:
SYP_encoder_struct enc1;
strcpy(enc1.name,"OSC1 Shape",strlen("OSC1 Shape"));
enc1.type = 0;
enc1.val_min = 0;
enc1.val_max = 127;
enc1.value = 0;
enc1.stepping = 1;
enc1.miditype = 0;
enc1.midicc = 20;
enc1.mapping = 0;
enc1.wordstart = 0;
enc1.ebpos = 0;
As to the union
aspect of the struct, the members .midicc
, .midirpn
, and .midinrpn
are members of an anonymous union, which means they can each be accessed directly i.e. enc1.midicc
, enc1.midirpn
, enc1.midinrpn
, but since they are members of a union inside the struct, they reside in overlapping memory, so it doesn't make sense to initialize more than one of them at a time.
If you want to initialize .midirpn
or .midinrpn
instead of .midicc
you can, but those three union members live on-top-of-each-other, so to speak, so only one can be used at a time.