I'm trying to convert following code into union Instruction in C:
typedef struct InstructionTypeI_t {
unsigned long immediate: 16;
unsigned char rt:5; // start a new byte
unsigned char rs : 5;
unsigned char opcode : 6;
} InstructionTypeI_t;
typedef struct InstructionTypeJ_t {
unsigned long address: 26;
unsigned char opcodce: 6;
} InstructionTypeJ_t;
typedef struct InstructionTypeR{
unsigned long funct: 6;
unsigned char shamt:5; // start a new byte
unsigned char rd : 5;
unsigned char rt : 5;
unsigned char rs: 5;
unsigned char opcode: 6;
} InstructionTypeR_t;
/* TODO Task (d) add union Instruction here */
typedef union Instruction{
InstructionTypeI_t i;
InstructionTypeJ_t j;
InstructionTypeR_t r;
}Instruction;
union Instruction instruction
InstructionTypeI_t i;
InstructionTypeJ_t j;
InstructionTypeR_t r;
interestingly this works
instruction.i=i;
instruction.j=j;
but this converts values wrong meaning for example instruction.i.opcode and i.opcode have different vlaues
instruction.i=i;
instruction.j=j;
instruction.r=r;
Any ideas what the problem could be?
CodePudding user response:
Adjacent bitfields have to have the same underlying type, otherwise they're not merged into the same instance of the underlying type.
I.e. by having an unsigned long
bitfield, followed by some unsigned char
ones, you get a full unsigned long
variable that only holds that single bitfield, and nothing else.
The solution is to use the same type for all those bitfields, probably uint32_t
or at least unsigned int
. I wouldn't use unsigned long
due to its non-portable size.