简体   繁体   English

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

[英]bit padded structure inside a union and typecasting

I have a unsigned 64-bit word and a bit padded structure which are both given below.The structure is inside a union which contains several(11 to be exact) similar but slightly structures. 我有一个无符号的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()

I want to interpret the 64 bits in the 64-bit word as fields in the structure.so I am doing the below operation 我想将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);

but I am not getting the expected values for the last field in my structure.Can anyone see any problem with what I am doing?Any suggestions or comments are appreciated. 但是我没有得到结构中最后一个字段的期望值。有人能看到我正在做的任何问题吗?欢迎提出任何建议或意见。

@Jonathan I have added the following comments to my code. @Jonathan我已在代码中添加了以下注释。
printf("sizeof(union) = %zu\\n", sizeof(block_payload_union_t)); printf(“ sizeof(union)=%zu \\ n”,sizeof(block_payload_union_t));

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

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

//printf("*bp->llp = 0x%.16lx\\n", *block_pload->llp); // 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-> 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_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_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_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_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_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_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_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); printf(“ bp-> cb1-> control_word_7 = 0x%.2X \\ n”,block_pload-> cb_1-> control_word_7);

The output I got without #pragma pack() was as follows 我没有#pragma pack()的输出如下

final data word 0x1e00000000000000 最终数据字0x1e00000000000000

sizeof(union) = 8 sizeof(union)= 8

sizeof(cb1) = 9 sizeof(cb1)= 9

FDW = 0x1e00000000000000 FDW = 0x1e00000000000000

bp->cb1->block_type_fld = 0x00 bp-> cb1-> block_type_fld = 0x00

bp->cb1->control_word_0 = 0x00 bp-> cb1-> control_word_0 = 0x00

bp->cb1->control_word_1 = 0x00 bp-> cb1-> control_word_1 = 0x00

bp->cb1->control_word_2 = 0x00 bp-> cb1-> control_word_2 = 0x00

bp->cb1->control_word_3 = 0x00 bp-> cb1-> control_word_3 = 0x00

bp->cb1->control_word_4 = 0x00 bp-> cb1-> control_word_4 = 0x00

bp->cb1->control_word_5 = 0x00 bp-> cb1-> control_word_5 = 0x00

bp->cb1->control_word_6 = 0x1E bp-> cb1-> control_word_6 = 0x1E

bp->cb1->control_word_7 = 0x78 bp-> cb1-> control_word_7 = 0x78

The output with #pragma pack() was as follows #pragma pack()的输出如下

final data word 0x1e00000000000000 最终数据字0x1e00000000000000

sizeof(union) = 8 sizeof(union)= 8

sizeof(cb1) = 8 sizeof(cb1)= 8

FDW = 0x1e00000000000000 FDW = 0x1e00000000000000

bp->cb1->block_type_fld = 0x00 bp-> cb1-> block_type_fld = 0x00

bp->cb1->control_word_0 = 0x00 bp-> cb1-> control_word_0 = 0x00

bp->cb1->control_word_1 = 0x00 bp-> cb1-> control_word_1 = 0x00

bp->cb1->control_word_2 = 0x00 bp-> cb1-> control_word_2 = 0x00

bp->cb1->control_word_3 = 0x00 bp-> cb1-> control_word_3 = 0x00

bp->cb1->control_word_4 = 0x00 bp-> cb1-> control_word_4 = 0x00

bp->cb1->control_word_5 = 0x00 bp-> cb1-> control_word_5 = 0x00

bp->cb1->control_word_6 = 0x00 bp-> cb1-> control_word_6 = 0x00

bp->cb1->control_word_7 = 0x0F bp-> cb1-> control_word_7 = 0x0F

which is similar to the output you got on Jonathan's machine. 这类似于您在乔纳森的机器上获得的输出。

You should be using sizeof(block_payload_union_t) instead of sizeof(block_payload_union_t *) in the call to malloc() . 您应该在对malloc()的调用中使用sizeof(block_payload_union_t)而不是sizeof(block_payload_union_t *) malloc() However, on a 64-bit machine, it probably gives you the same size (8), so you get away with it, for all it is wrong. 但是,在64位计算机上,它可能会为您提供相同的大小(8),因此您可以不使用它,因为这是完全错误的。

It is slightly odd that your block_payload_union_t contains pointers to your field layouts instead of holding the actual values. 您的block_payload_union_t包含指向字段布局的指针,而不是包含实际值,这有点奇怪。

You have not shown us the declaration of final_data_word . 您尚未向我们显示final_data_word的声明。 Have you checked the size of your union versus the size you expect? 您是否检查了工会的规模与预期的规模?


On a Mac running Lion (10.7.2), I get this output from the program which follows: 在运行Lion(10.7.2)的Mac上,我从以下程序获得以下输出:

Output 输出量

With #pragma pack(1) : 使用#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

Without #pragma pack(1) : 没有#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

What are you getting? 你得到什么?

Program 程序

#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);
}

What's the point in having pointers as members in your union? 将指针作为您工会的成员有什么意义? You could achieve the same result via casts. 您可以通过强制转换获得相同的结果。

If what you want is to access the data (and not the pointers) through the eleven different structures, then in the union you don't want to use pointers but the structs directly: 如果要通过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;

Now the size of your block_payload_union_t struct is just 64-bits, and you can work with this data using any of the eleven versions. 现在, block_payload_union_t结构的大小仅为64位,您可以使用十一个版本中的任何一个来处理此数据。

#pragma pack(1) directive would cause that member to be packed in the structure on a 1-byte boundary, however #pragma pack directive aligns all bit fields in a structure/union on 1-bit boundaries. #pragma pack(1)指令将导致该成员在1字节边界上打包到结构中,但是#pragma pack指令在1位边界上将结构/联合中的所有位字段对齐。 This is why the last field is kicked off. 这就是最后一场比赛开始的原因。 Check the sizeof of control_block_format_1_s whether it is 8 or 9. 检查control_block_format_1_ssizeof是8还是9。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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