I am facing a strange issue when using #pragma pack
.
I have the following structs:
st_a
: packed with#pragma pack(1)
. Size = 1 byte. Contains bitfields.st_b
: packed with#pragma pack(2)
. Size = 14 bytes.st_c
: packed with#pragma pack(2)
. Size = 16 bytes. Containsst_a
andst_b
st_d
: packed with#pragma pack(2)
. Size = 16 bytes. Containsst_a
and contents ofst_b
(st_b
's members)
So, since st_a
is of 1 byte packed under #pragma pack(1)
, and since it's inside st_c
which is packed under #pragma pack(2)
, there should be one extra byte of padding in st_c
immediately after st_a
and that extra byte should be followed by contents of st_b
which is a character buffer of even length (10).
But, this thing works strangely when I take the contents of st_b
out and put them directly in st_a
. The padding is seen after the character buffer, rather than before (See output below).
Can somebody explain, why this strange behavior occurs?
Code:
#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;
}
Output:
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
Note: I am using GCC version 4.4.x.
Some notes about the output:
In first line, 5b
is the padding byte introduced between 4
which is 1 byte st_a
and 41
which is the first character of buffer of st_b
.
In second line, 0
is the padding byte introduced between 4a
which is last character of buffer and a
which is the integer following the character buffer in st_d
.
Third line prints the size of all the structures.