Home > database >  Initialize struct with a union inside
Initialize struct with a union inside

Time:08-04

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.

  • Related