我在使用时遇到了一个奇怪的问题#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
is 有 1 个字节打包在 下#pragma pack(1)
,并且由于它在里面st_c
打包在 下#pragma pack(2)
,因此应该有一个额外的填充字节st_c
紧随其后st_a
,并且该额外字节后面应该是st_b
偶数长度的字符缓冲区的内容(10 )。
但是,当我把st_b
out 的内容直接放入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
。
第三行打印所有结构的大小。