Пытаюсь упаковать данные в пакет. Этот пакет должен быть 64-битным. У меня есть это:
typedef union {
uint64_t raw;
struct {
unsigned int magic : 8;
unsigned int parity : 1;
unsigned int stype : 8;
unsigned int sid : 8;
unsigned int mlength : 31;
unsigned int message : 8;
} spacket;
} packet_t;
Но кажется, что выравнивание не гарантируется. Потому что, когда я запускаю это:
#include <strings.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
const char *number_to_binary(uint64_t x)
{
static char b[65];
b[64] = '\0';
uint64_t z;
int w = 0;
for (z = 1; w < 64; z <<= 1, ++w)
{
b[w] = ((x & z) == z) ? '1' : '0';
}
return b;
}
int main(void)
{
packet_t ipacket;
bzero(&ipacket, sizeof(packet_t));
ipacket.spacket.magic = 255;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.parity = 1;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.stype = 255;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.sid = 255;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.mlength = 2147483647;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.message = 255;
printf("%s\n", number_to_binary(ipacket.raw));
}
Я получаю (старший порядок байтов):
1111111100000000000000000000000000000000000000000000000000000000
1111111110000000000000000000000000000000000000000000000000000000
1111111111111111100000000000000000000000000000000000000000000000
1111111111111111111111111000000000000000000000000000000000000000
1111111111111111111111111000000011111111111111111111111111111110
1111111111111111111111111000000011111111111111111111111111111110
Мое поле .mlength
потеряно где-то в правой части, хотя оно должно быть прямо рядом с полем .sid
.
Эта страница подтверждает это: Выравнивание единицы распределения, содержащей битовое поле не указано. Но если это так, как люди упаковывают данные в битовые поля, что является их целью в первую очередь?
24 бита, по-видимому, являются максимальным размером, который поле .mlength
может принять до того, как поле .message
будет удалено.
char
еще хуже. - person too honest for this site   schedule 16.04.2016uint8_t
и т. д. недоступны, причина в том, что ваша архитектура не поддерживает требуемую ширину или (для подписанных типов) представление. Что в конечном итоге сломает любой код, полагающийся на ширину стандартных типов. Таким образом, использование(u)intN_t
является еще одной системой безопасности для вашей реализации. - person too honest for this site   schedule 17.04.2016