简体   繁体   中英

C struct, union pointer to struct

I have a typedeffed struct and an union. The union contains the struct and a single uint32_t . The goal is to assign a value to foo that corresponds to the 'bits' in the struct.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct {
    uint32_t valA :1;
    uint32_t valB :1;
    uint32_t valC :1;
    uint32_t valD :1;
    uint32_t valE :1;
} ValStruct_Type;

typedef union {
    ValStruct_Type valStruct;
    uint32_t valUint;
} ValUnion_Type;

uint32_t foo = 0;


int main(void)
{
    ValStruct_Type Vals;
    Vals.valA = 0x0;
    Vals.valB = 0x1;
    Vals.valC = 0x0;
    Vals.valD = 0x1;
    Vals.valE = 0x1;

    ValStruct_Type *Vals_ptr;
    Vals_ptr = &Vals;

    foo = ((ValUnion_Type *)Vals_ptr)->valUint;

    return 0;
}

foo becomes:

Decimal:    4194330
Hex:        0x40001a
Binary:     10000000000000000011010

Who can explain what is happening here exactly (union pointer to a struct pointer, defererenced to a union member?)?

Secondly: why is bit 22 of foo set in addition to bit 1,3 and 4?

Bit 22 is set due to undefined behavior. You've created a local variable that you never fully initialized, and you then set 5 bits of it. The remaining bits are whatever they happen to be, which is the case with uninitialized locals.

Regarding the first part of your question... what isn't clear? Your question ( union pointer to a struct pointer, defererenced to a union member ) seems to answer itself. Casting something to the type it already is doesn't have any effect.

When you define a union you instruct the compiler to reserve enough memory for any instances that can fit either of it's members.

When you typedef a bitfield it is padded to some byte size (normally 4 or 8 bytes, but could be 1 byte in your small case).

Since you only allocated enough memory for your struct (check with sizeof(ValStruct_Type) ) and then cast it to a union taking up more memory you got undefined behaviour.

Whatever filled up that part of your stack was copied into foo .

What you approximately did equals to

char a = 0x1a;
int foo = *(int *)&a;

To get the correct behaviour you need to

  • allocate the union
  • initialise it
  • then start setting your bitfield.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM