printf问题

近日在工作中遇到一个奇怪问题,A程序发送一个结构给B程序,在B程序接收后,B程序按照A程序的结构进行解析,但始终不对。看过结构定义后,虽然知道有可能会出现字节对齐问题,一直怀疑是他们消息传输构造不对。经过GDB确认A程序发出的结构是正确的,在B程序接收处也同样没问题。当调试到转化处时才发现确实是字节对齐导致的。下面举例说明(32bit Linux Gcc)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
typedef struct
{
unsigned int a;
short int b;
long long int c;
unsigned int d;
}type1;

int main(int argc,char *argv[])
{
type1 A={1,2,0x1234567890123456LL,0x87654321},B,*C;
B=A;
C=&A;
printf("B={0x%x,0x%x,0x%x,0x%x}\n",B.a,B.b,B.c,B.d);
printf("C={0x%x,0x%x,0x%x,0x%x}\n",C->a,C->b,C->c,C->d);
return 0;
}

输出:
B={0x1,0x2,0x3,0x0}
C={0x1,0x2,0x3,0x0}

从上面这个示例可以看出,输出的结果与我们预期的不一样。这是因为在32位系统下,数据存储将按结构体成员的最大字节数对齐,并且最大字节数为4。因此如type1结构体将按4字节对齐,变量A/B/C字节流为:

01 00 00 00 02 00 00 00 03 00 00 00 00 00 00 00 04 00 00 00

GDB显示如下,其中b显示0x02 0x00 0x04 0x08,是由于没有清掉之前的缓存。

1
2
3
4
5
6
(gdb) x/30x C
0xbffff328: 0x01 0x00 0x00 0x00 0x02 0x00 0x04 0x08
0xbffff330: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xbffff338: 0x04 0x00 0x00 0x00 0x28 0xf3 0xff 0xbf
0xbffff340: 0xd0 0x84 0x04 0x08 0xf4 0xff
(gdb)