При использовании #pragma pack
.
я столкнулся со странной проблемой.
У меня есть следующие структуры:
st_a
: упаковано с #pragma pack(1)
. Размер = 1 байт. Содержит битовые поля.
st_b
: упаковано с #pragma pack(2)
. Размер = 14 байт.
st_c
: упаковано с #pragma pack(2)
. Размер = 16 байт. Содержит st_a
и st_b
st_d
: упаковано с #pragma pack(2)
. Размер = 16 байт. Содержит st_a
и содержимое st_b
(st_b
)
Итак, поскольку st_a
имеет 1 байт, упакованный в #pragma pack(1)
, и поскольку он находится внутри st_c
, который упакован в #pragma pack(2)
, должен быть один дополнительный байт заполнения в st_c
сразу после st_a
и за этим дополнительным байтом должно следовать содержимое st_b
, которое является символьным буфером четной длины (10).
Но эта штука работает странно, когда я вынимаю содержимое st_b
и помещаю его прямо в st_a
. Заполнение отображается после символьного буфера, а не до (см. Вывод ниже).
Может кто-нибудь объяснить, почему происходит это странное поведение?
Код:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#pragma pack(push)
#pragma pack(1)
typedef struct A {
int a : 1;
int b : 1;
int c : 1;
int d : 1;
int e : 1;
int f : 1;
int g : 1;
int h : 1;
} st_a;
#pragma pack(pop)
#pragma pack(push)
#pragma pack(2)
typedef struct B {
unsigned char buf[10];
int x;
} st_b;
typedef struct C {
st_a temp1;
st_b temp2;
} st_c;
typedef struct D {
st_a temp3;
unsigned char buf1[10];
int x1;
} st_d;
#pragma pack(pop)
void print_hex(unsigned char* packet) {
for (int i = 0; i < 16; i++) {
printf("%x ", packet[i]);
} printf("\n");
}
int main() {
st_c one;
one.temp1.a = 0;
one.temp1.b = 0;
one.temp1.c = 1;
one.temp1.d = 0;
one.temp1.e = 0;
one.temp1.f = 0;
one.temp1.g = 0;
one.temp1.h = 0;
memcpy(&one.temp2.buf, "ABCDEFGHIJ", 10);
one.temp2.x = 10;
st_d two;
two.temp3.a = 0;
two.temp3.b = 0;
two.temp3.c = 1;
two.temp3.d = 0;
two.temp3.e = 0;
two.temp3.f = 0;
two.temp3.g = 0;
two.temp3.h = 0;
memcpy(&two.buf1, "ABCDEFGHIJ", 10);
two.x1 = 10;
print_hex((unsigned char*) &one);
print_hex((unsigned char*) &two);
cout << sizeof(st_c) << " " << sizeof(st_a) << " " << sizeof(st_b) << " " << sizeof(st_d) << endl;
return 0;
}
Выход:
4 5b 41 42 43 44 45 46 47 48 49 4a a 0 0 0
4 41 42 43 44 45 46 47 48 49 4a 0 a 0 0 0
16 1 14 16
Примечание. Я использую GCC версии 4.4.x.
Несколько замечаний по поводу вывода :
В первой строке 5b
- это байт заполнения, введенный между 4
, который равен 1 байту st_a
и 41
, который является первым символом буфера st_b
.
Во второй строке 0
- это байт заполнения, введенный между 4a
, который является последним символом буфера, и a
, который является целым числом после символьного буфера в st_d
.
Третья строка печатает размер всех структур.