联合和类型转换中的位填充结构

时间:2011-11-11 05:33:23

标签: c struct unions

我有一个无符号的64位字和一个位填充结构,它们都在下面给出。结构在一个联合内部,它包含几个(11个准确)相似但略微结构。

uint64_t final_data_word;

#pragma pack(1)
typedef struct control_block_format_1_s
{
    uint8_t block_type_field:8;
    uint8_t control_word_0:7;
    uint8_t control_word_1:7;
    uint8_t control_word_2:7;
    uint8_t control_word_3:7;
    uint8_t control_word_4:7;
    uint8_t control_word_5:7;
    uint8_t control_word_6:7;
    uint8_t control_word_7:7;
}control_block_format_1_t;

typedef union
{
    control_block_format_1_t *cb_1;
    control_block_format_2_t *cb_2;
    control_block_format_3_t *cb_3;
    control_block_format_4_t *cb_4;
    control_block_format_5_t *cb_5;
    control_block_format_6_t *cb_6;
    control_block_format_7_t *cb_7;
    control_block_format_8_t *cb_8;
    control_block_format_9_t *cb_9;
    control_block_format_10_t *cb_10;
    control_block_format_11_t *cb_11;
}block_payload_union_t;
#pragma pack()

我想将64位字中的64位解释为结构中的字段。所以我正在进行以下操作

block_payload_union_t *block_pload =(block_payload_union_t*)malloc(sizeof(block_payload_union_t*));
block_pload->cb_1 = (control_block_format_1_t*)(&final_data_word);

但我没有得到我的结构中最后一个字段的预期值。任何人都可以看到我正在做的任何问题吗?任何建议或意见都表示赞赏。

@Jonathan 我在代码中添加了以下注释    printf(" sizeof(union)=%zu \ n",sizeof(block_payload_union_t));

   printf(" sizeof(cb1)=%zu \ n",sizeof(control_block_format_1_t));

   printf(" FDW = 0x%.16lx \ n",final_data_word);

// printf(" * bp-> llp = 0x%.16lx \ n",* block_pload-> llp);

   printf(" bp-> cb1-> block_type_fld = 0x%。2X \ n",block_pload-> cb_1-> block_type_field);

   printf(" bp-> cb1-> control_word_0 = 0x%。2X \ n",block_pload-> cb_1-> control_word_0);

   printf(" bp-> cb1-> control_word_1 = 0x%。2X \ n",block_pload-> cb_1-> control_word_1);

   printf(" bp-> cb1-> control_word_2 = 0x%。2X \ n",block_pload-> cb_1-> control_word_2);

   printf(" bp-> cb1-> control_word_3 = 0x%。2X \ n",block_pload-> cb_1-> control_word_3);

   printf(" bp-> cb1-> control_word_4 = 0x%。2X \ n",block_pload-> cb_1-> control_word_4);

   printf(" bp-> cb1-> control_word_5 = 0x%。2X \ n",block_pload-> cb_1-> control_word_5);

   printf(" bp-> cb1-> control_word_6 = 0x%。2X \ n",block_pload-> cb_1-> control_word_6);

   printf(" bp-> cb1-> control_word_7 = 0x%。2X \ n",block_pload-> cb_1-> control_word_7);

没有#pragma pack()的输出如下:

最终数据字0x1e00000000000000

sizeof(union)= 8

sizeof(cb1)= 9

FDW = 0x1e00000000000000

bp-> cb1-> block_type_fld = 0x00

bp-> cb1-> control_word_0 = 0x00

bp-> cb1-> control_word_1 = 0x00

bp-> cb1-> control_word_2 = 0x00

bp-> cb1-> control_word_3 = 0x00

bp-> cb1-> control_word_4 = 0x00

bp-> cb1-> control_word_5 = 0x00

bp-> cb1-> control_word_6 = 0x1E

bp-> cb1-> control_word_7 = 0x78

#pragma pack()的输出如下:

最终数据字0x1e00000000000000

sizeof(union)= 8

sizeof(cb1)= 8

FDW = 0x1e00000000000000

bp-> cb1-> block_type_fld = 0x00

bp-> cb1-> control_word_0 = 0x00

bp-> cb1-> control_word_1 = 0x00

bp-> cb1-> control_word_2 = 0x00

bp-> cb1-> control_word_3 = 0x00

bp-> cb1-> control_word_4 = 0x00

bp-> cb1-> control_word_5 = 0x00

bp-> cb1-> control_word_6 = 0x00

bp-> cb1-> control_word_7 = 0x0F

这与Jonathan的机器上的输出相似。

3 个答案:

答案 0 :(得分:3)

您应该在sizeof(block_payload_union_t)的通话中使用sizeof(block_payload_union_t *)代替malloc()。但是,在64位计算机上,它可能会给你相同的大小(8),所以你可以逃脱它,因为它是错误的。

您的block_payload_union_t包含指向字段布局的指针而不是保留实际值,这有点奇怪。

您尚未向我们展示final_data_word的声明。您是否检查了工会的规模与预期的规模?


在运行Lion(10.7.2)的Mac上,我从以下程序获得此输出:

输出

使用#pragma pack(1)

sizeof(union) = 8
sizeof(cb1) = 8
FDW = 0xFEDCBA9876543210
*bp->llp = 0xFEDCBA9876543210
bp->cb1->block_type_fld = 0x10
bp->cb1->control_word_0 = 0x32
bp->cb1->control_word_1 = 0x28
bp->cb1->control_word_2 = 0x59
bp->cb1->control_word_3 = 0x43
bp->cb1->control_word_4 = 0x29
bp->cb1->control_word_5 = 0x17
bp->cb1->control_word_6 = 0x37
bp->cb1->control_word_7 = 0x7F

没有#pragma pack(1)

sizeof(union) = 8
sizeof(cb1) = 9
FDW = 0xFEDCBA9876543210
*bp->llp = 0xFEDCBA9876543210
bp->cb1->block_type_fld = 0x10
bp->cb1->control_word_0 = 0x32
bp->cb1->control_word_1 = 0x54
bp->cb1->control_word_2 = 0x76
bp->cb1->control_word_3 = 0x18
bp->cb1->control_word_4 = 0x3A
bp->cb1->control_word_5 = 0x5C
bp->cb1->control_word_6 = 0x7E
bp->cb1->control_word_7 = 0x10

你得到了什么?

程序

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

#pragma pack(1)
typedef struct control_block_format_1_s
{
    uint8_t block_type_field:8;
    uint8_t control_word_0:7;
    uint8_t control_word_1:7;
    uint8_t control_word_2:7;
    uint8_t control_word_3:7;
    uint8_t control_word_4:7;
    uint8_t control_word_5:7;
    uint8_t control_word_6:7;
    uint8_t control_word_7:7;
} control_block_format_1_t;

typedef union
{
    long long *llp;
    control_block_format_1_t *cb_1;
    //control_block_format_2_t *cb_2;
    //control_block_format_3_t *cb_3;
    //control_block_format_4_t *cb_4;
    //control_block_format_5_t *cb_5;
    //control_block_format_6_t *cb_6;
    //control_block_format_7_t *cb_7;
    //control_block_format_8_t *cb_8;
    //control_block_format_9_t *cb_9;
    //control_block_format_10_t *cb_10;
    //control_block_format_11_t *cb_11;
} block_payload_union_t;
#pragma pack()

int main(void)
{
    long long final_data_word = 0xFEDCBA9876543210;
    block_payload_union_t *block_pload =(block_payload_union_t*)malloc(sizeof(block_payload_union_t));
    block_pload->cb_1 = (control_block_format_1_t*)(&final_data_word);
    printf("sizeof(union) = %zu\n", sizeof(block_payload_union_t));
    printf("sizeof(cb1) = %zu\n", sizeof(control_block_format_1_t));
    printf("FDW = 0x%.16llX\n", final_data_word);
    printf("*bp->llp = 0x%.16llX\n", *block_pload->llp);
    printf("bp->cb1->block_type_fld = 0x%.2X\n", block_pload->cb_1->block_type_field);
    printf("bp->cb1->control_word_0 = 0x%.2X\n", block_pload->cb_1->control_word_0);
    printf("bp->cb1->control_word_1 = 0x%.2X\n", block_pload->cb_1->control_word_1);
    printf("bp->cb1->control_word_2 = 0x%.2X\n", block_pload->cb_1->control_word_2);
    printf("bp->cb1->control_word_3 = 0x%.2X\n", block_pload->cb_1->control_word_3);
    printf("bp->cb1->control_word_4 = 0x%.2X\n", block_pload->cb_1->control_word_4);
    printf("bp->cb1->control_word_5 = 0x%.2X\n", block_pload->cb_1->control_word_5);
    printf("bp->cb1->control_word_6 = 0x%.2X\n", block_pload->cb_1->control_word_6);
    printf("bp->cb1->control_word_7 = 0x%.2X\n", block_pload->cb_1->control_word_7);
    return(0);
}

答案 1 :(得分:2)

将指针作为你工会的成员有什么意义?你可以通过演员表获得相同的结果。

如果你想要的是通过11个不同的结构访问数据(而不是指针),那么在联合中你不想直接使用指针而是结构:

typedef union
{
    control_block_format_1_t cb_1;
    control_block_format_2_t cb_2;
    control_block_format_3_t cb_3;
    control_block_format_4_t cb_4;
    control_block_format_5_t cb_5;
    control_block_format_6_t cb_6;
    control_block_format_7_t cb_7;
    control_block_format_8_t cb_8;
    control_block_format_9_t cb_9;
    control_block_format_10_t cb_10;
    control_block_format_11_t cb_11;
} block_payload_union_t;

现在block_payload_union_t结构的大小只有64位,您可以使用11个版本中的任何一个来处理这些数据。

答案 2 :(得分:2)

#pragma pack(1)指令会导致该成员在1字节边界的结构中打包,但是 #pragma pack 指令会对齐所有位字段在1位边界的结构/联合中。这就是最后一个领域开始的原因。检查 control_block_format_1_s sizeof ,无论是8还是9。