#c #struct #unions
#c #структура #объединения
Вопрос:
У меня есть неподписанное 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-разрядном word как поля в структуре.итак, я выполняю приведенную ниже операцию
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*)(amp;final_data_word);
но я не получаю ожидаемые значения для последнего поля в моей структуре.Кто-нибудь видит какие-либо проблемы с тем, что я делаю?Приветствуются любые предложения или комментарии.
@Jonathan Я добавил следующие комментарии к своему коду.
printf(«sizeof(объединение) = %zun», sizeof(block_payload_union_t));
printf(«sizeof(cb1) = %zun», sizeof(control_block_format_1_t));
printf(«FDW = 0x%.16lxn», final_data_word);
//printf(«*bp-> llp = 0x%.16lxn», *block_pload->llp);
printf(«bp->cb1->block_type_fld = 0x%.2Xn», block_pload->cb_1->block_type_field);
printf(«bp->cb1->control_word_0 = 0x%.2Xn», block_pload->cb_1->control_word_0);
printf(«bp-> cb1->control_word_1 = 0x%.2Xn», block_pload->cb_1->control_word_1);
printf(«bp->cb1->control_word_2 = 0x%.2Xn», block_pload->cb_1->control_word_2);
printf(«bp-> cb1->control_word_3 = 0x%.2Xn», block_pload->cb_1->control_word_3);
printf(«bp->cb1->control_word_4 = 0x%.2Xn», block_pload->cb_1->control_word_4);
printf(«bp->cb1->control_word_5 = 0x%.2Xn», block_pload->cb_1->control_word_5);
printf(«bp-> cb1->control_word_6 = 0x%.2Xn», block_pload->cb_1->control_word_6);
printf(«bp->cb1->control_word_7 = 0x%.2Xn», block_pload->cb_1->control_word_7);
Результат, который я получил без #pragma pack (), был следующим
конечное слово данных 0x1e00000000000000
sizeof (объединение) = 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 (объединение) = 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
которая похожа на результат, который вы получили на компьютере Джонатана.
Комментарии:
1. Похоже, вас смущает разница между объектом и указателем на объект
Ответ №1:
Вы должны использовать 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*)(amp;final_data_word);
printf("sizeof(union) = %zun", sizeof(block_payload_union_t));
printf("sizeof(cb1) = %zun", sizeof(control_block_format_1_t));
printf("FDW = 0x%.16llXn", final_data_word);
printf("*bp->llp = 0x%.16llXn", *block_pload->llp);
printf("bp->cb1->block_type_fld = 0x%.2Xn", block_pload->cb_1->block_type_field);
printf("bp->cb1->control_word_0 = 0x%.2Xn", block_pload->cb_1->control_word_0);
printf("bp->cb1->control_word_1 = 0x%.2Xn", block_pload->cb_1->control_word_1);
printf("bp->cb1->control_word_2 = 0x%.2Xn", block_pload->cb_1->control_word_2);
printf("bp->cb1->control_word_3 = 0x%.2Xn", block_pload->cb_1->control_word_3);
printf("bp->cb1->control_word_4 = 0x%.2Xn", block_pload->cb_1->control_word_4);
printf("bp->cb1->control_word_5 = 0x%.2Xn", block_pload->cb_1->control_word_5);
printf("bp->cb1->control_word_6 = 0x%.2Xn", block_pload->cb_1->control_word_6);
printf("bp->cb1->control_word_7 = 0x%.2Xn", block_pload->cb_1->control_word_7);
return(0);
}
Комментарии:
1. Я не совсем понимаю, что означает этот комментарий. Я не вижу код, на который вы смотрите. Вы также могли бы рассмотреть возможность определения платформы, на которой вы работаете, и используемого компилятора. (Я сказал macOS X 10.7.2; я должен был упомянуть XCode 4.2 от Apple (GCC 4.2.1 для LLVM).)
Ответ №2:
Какой смысл иметь указателей в качестве членов вашего профсоюза? Вы могли бы достичь того же результата с помощью приведений.
Если вы хотите получить доступ к данным (а не к указателям) через одиннадцать различных структур, то в объединении вы хотите использовать не указатели, а структуры напрямую:
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 бита, и вы можете работать с этими данными, используя любую из одиннадцати версий.
Ответ №3:
Директива #pragma pack(1) приведет к тому, что этот элемент будет упакован в структуру с 1-байтовой границей, однако директива #pragma pack выравнивает все битовые поля в структуре / объединении по 1-битным границам. Вот почему последнее поле отключено. Проверьте размер control_block_format_1_s, равен ли он 8 или 9.