0

我有一个 typedefed 结构和一个联合。联合包含结构和单个uint32_t. foo目标是为结构中的“位”分配一个值。

#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 变为:

Decimal:    4194330
Hex:        0x40001a
Binary:     10000000000000000011010

谁能准确地解释这里发生了什么(指向结构指针的联合指针,尊重联合成员?)?

其次:为什么foo除了第 1,3 和 4 位之外还有 set 的第 22 位?

4

2 回答 2

2

由于未定义的行为,第 22 位被设置。您创建了一个从未完全初始化过的局部变量,然后设置了 5 位。剩下的位就是它们碰巧是什么,未初始化的本地人就是这种情况。

关于你问题的第一部分......什么不清楚?您的问题 ( union pointer to a struct pointer, defererenced to a union member) 似乎可以自行回答。将某些东西转换为它已经是的类型没有任何效果。

于 2013-08-08T11:00:27.873 回答
1

当你定义一个联合时,你指示编译器为任何可以容纳它的任何一个成员的实例保留足够的内存。

当你 typedef 一个位域时,它被填充到某个字节大小(通常是 4 或 8 个字节,但在你的小情况下可能是 1 个字节)。

由于您只为您的结构分配了足够的内存(检查sizeof(ValStruct_Type)),然后将其强制转换为占用更多内存的联合,您会得到未定义的行为。

任何填充了堆栈的那部分的内容都被复制到foo.

你所做的大约等于

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

要获得正确的行为,您需要

  • 分配工会
  • 初始化它
  • 然后开始设置你的位域。
于 2013-08-08T11:02:24.363 回答