|
sizeof union, Си |
|
|
|
Oct 14 2009, 19:07
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Код typedef union { int asHeader;
struct { int header; int int1; int int2; int int3; }asInt3;
struct { int header; char array[30]; }asArray; }my_union;
const int asInt3_size = sizeof(my_union.asInt3); // error: expected a ")" т.е. предлагает мне сделать sizeof(my_union); А я бы очень хотел получить размеры каждого члена(или как там правильно его назвать) юниона. Задумка такая: одной переменной описать три разных типа пакета, отличающиеся длиной и типом поля data. Однако первые n байт всех трёх типов пакетов одинаковы и соответствуют заголовку(header). Отправлять планируется в зависимости от надобности либо sizeof(my_union.asHeader); либо sizeof(my_union.asInt3) либо sizeof(my_union.asArray); байтов. Header содержит поле, описывающее тип пакета, соответственно принемающая сторона всегда будет знать как трактовать пришедший пакет, сначала проанализировав это поле по my_union.asHeader; К тому-же иногда(для подтверждения доставки) достаточно отправить просто asHeader. Привлекательность состоит в том, что весь union займет в памяти столько месте, сколько необходимо для самого жирного члена(sizeof(asArray)) а AsHeader будет равен asArray.header и asInt3.header - потому как по идее &my_union_var.asHeader == &my_union_var.asInt3.header == &my_union_var.asArray.header Верно ли последнее предположение по поводу header и как взять sizeof от члена union? Или же поступить проще и определить структуры asHeader, asInt3, asArray отдельными typedef'ами, а union просто будет: Код typedef union { asHeader_type asHeader; asInt3_type asInt3; asArray_type asArray; }my_union;
const int asInt3_size = sizeof(asInt3_type); P.S. Ссылочку на стандарт С99 мне подкинули, но оказалось что сходу там ответ найти бывает очень сложно.
--------------------
The truth is out there...
|
|
|
|
|
Oct 14 2009, 19:15
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Код const int asInt3_size = sizeof(my_union.asInt3);
const int asInt3_size = sizeof(((my_union *)0)->asInt3); Один из вариантов должон сработать. Проверять лень. ------------- PS. отредактировано уже после нижестоящего поста.
Сообщение отредактировал GetSmart - Oct 14 2009, 19:50
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 14 2009, 20:56
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Ну как сказать. можно и указатели, можно и разные типы. В функции можно передавать void *, а там уже делать с ним что хочешь. А почему не любите? Я тут как-бы может быть слегка вдохновленный возможностями Си и разошелся маленько. В общем суть такова: Код /* * Размер пакета может меняться в зависимости от настройки алгоритма(размер блока, размер поля ID(публ. ключа)) * * Нам нужны пакеты двух типов * 1.ID-пакет: используется для передачи ID абонентов и ID корпорации * 2.Block-пакет: предназначен для транспорта данных длиной в 1 блок(хэш-функция, случайная выборка) * Но для унификации функций обработки пакетов яввел union ba05_net_packet */ enum conn_stages{ public_keys_interchange, random_sample_interchange, hash_interchange };//стадии соединения enum packetTypes{ IDPacket, BlockPacket }; //заголовок у обоих типов пакетов общий, поэтому опишем его один раз typedef struct { enum packetTypes packetType; enum conn_stages connStageID; unsigned needACK : 1; //сообщает приёмнику, что в ответ на этот пакет нужно обязательно отправить ACK пакет unsigned ACK : 1; //Признак пакета подтверждения. Если ACK==1 - все остальные поля не используются(кроме crc8,естественно) unsigned crc8 : 8; }ba05_net_pktHeader;
//этот union позволяет использовать один тип данных(ba05_net_packet) для обоих типов пакетов. typedef union { ba05_net_pktHeader header; //иногда нужен _только_ заголовок пакета. К нему можно удобно обратиться :) struct { ba05_net_pktHeader header; ba05_ID master_ID; ba05_ID slave_ID; ba05_ID slave_corpID; }asIDPacket;//1.ID-пакет: используется для передачи ID абонентов и ID корпорации struct { ba05_net_pktHeader header; ba05_blockKey data; }asBlockPacket;//2.Block-пакет: предназначен для транспорта данных длиной в 1 блок }ba05_net_packet;
enum { BlockPacketSize = sizeof(((ba05_net_packet *)0)->asBlockPacket), IDPacketSize = sizeof(((ba05_net_packet *)0)->asIDPacket), HeaderPacketSize = sizeof(((ba05_net_packet *)0)->header) }; По-моему достаточно элегантно выходит. Но оценить объективно свой подход бывает достаточно сложно. Поэтому реквестирую кАменты знатоков
--------------------
The truth is out there...
|
|
|
|
|
Oct 14 2009, 22:14
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Отлично! Благодарю. Действительно, немножко не с той стороны подошел  Хорошо. Тут вот более глубоко задумался над typedef.... видимо ещё паскалевский стиль мышления заставляет воспринемать структуру как новый тип данных(ну и, естественно, сразу в голову приходит typedef) Так вот, собственно, так-же известно, что ту-же структуру можно определить без typedef, а потом точно так-же определять структурные переменные. Вопрос в том, чем отличается Цитата struct my_struct { int field1; int fieeld2; }; //а потом my_struct my_struct_var; от Цитата typedef struct { int field1; int fieeld2; }my_struct; //а потом my_struct my_struct_var; Разница ведь только в области видимости? т.е. typedef действительно глобальный, а тег структуры(при объявлении по первому методу) будет иметь область видимости ограниченную файлом. Я ничего не упустил? А то наплодил typedef а теперь вот задумался, что может быть абсолютно напрасно
--------------------
The truth is out there...
|
|
|
|
|
Oct 15 2009, 08:03
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(sigmaN @ Oct 15 2009, 02:14)  Разница ведь только в области видимости? Если вы используете С++ то разницы нет! А если С, то при каждом объявлении надо будет писать: struct my_struct my_struct_var; вот что бы не писать слово struct каждый раз и используют typedef.
|
|
|
|
|
Nov 3 2009, 23:54
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(sigmaN @ Oct 15 2009, 10:24)  Понятно. Значит буду продолжать typedef. В принципе он мне нравится Тогда еще одит "trick" на примере приведенном zltigoКод typedef struct tag_ba05_net_packet { struct tag_ba05_net_packet *pNextPacket; // иногда полезно когда пакеты связаны
ba05_net_pktHeader header; //иногда нужен _только_ заголовок пакета. К нему можно удобно обратиться :) union{ asIDBody; ba05_blockKey; }; } ba05_net_packet_t, *ba05_net_packet_ptr_t; Сразу и список пакетов формировать можно и указатель на пакет объявлен.
|
|
|
|
|
Nov 5 2009, 01:52
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(GetSmart @ Nov 4 2009, 23:56)  Это что такое? Нетипизированные поля? Этот кусочек я отцитировал. Думаю там предполагались структуры: Код union { zzz_t zzz; xxx_t xxx; }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|