битовая структура внутри объединения и типографской обработки - PullRequest
0 голосов
/ 11 ноября 2011

У меня есть 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);

, но я не получаю ожидаемые значения для последнего поля в моемструктура. Может кто-нибудь видеть какие-либо проблемы с тем, что я делаю? Любые предложения или комментарии приветствуются.

@ Джонатан Я добавил следующие комментарии к своему коду.
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
Это похоже на вывод, который вы получили на машине Джонатана.

Ответы [ 3 ]

3 голосов
/ 11 ноября 2011

Вы должны использовать sizeof(block_payload_union_t) вместо sizeof(block_payload_union_t *) при вызове malloc(). Однако на 64-битной машине он, вероятно, дает такой же размер (8), что вам это сойдет с рук, в общем-то, это неправильно.

Немного странно, что ваш block_payload_union_t содержит указатели на макеты полей вместо хранения фактических значений.

Вы не показали нам декларацию final_data_word. Вы проверяли размер своего союза по сравнению с ожидаемым размером?


На Mac под управлением Lion (10.7.2) я получаю следующие выходные данные программы:

выход

С #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);
}
2 голосов
/ 11 ноября 2011
Директива

# pragma pack (1) приведет к тому, что этот элемент будет упакован в структуру на 1-байтовой границе, однако директива # pragma pack выравнивает все битовые поля вструктура / объединение на 1-битных границах.Вот почему последнее поле запускается.Проверьте размер из control_block_format_1_s , 8 или 9.

2 голосов
/ 11 ноября 2011

Какой смысл иметь указателей в качестве членов в вашем союзе?Вы можете достичь того же результата с помощью приведения.

Если вам нужен доступ к данным (а не указателям) через одиннадцать различных структур, то в объединении вы не хотите использовать указатели, кроместруктура напрямую:

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 бита, и вы можете работать с этими данными, используя любую из одиннадцати версий.

...