吃亏在四字节对齐
我在写程序的时候遇到一个问题,费了我半天的时间才找到答案,记录如下:
我原来一个程序有如下结构:
UCHAR Rx_buf[MAX_BUF];
typedef struct //本结构体保证四字节对齐
{
UCHAR _station;
UCHAR _command;
…
UINT32 _offset;
} Protocol;
//程序片断
Protocol *proto;
…
For(i=0; i<sizeof(Protocol); i++)
Tx_buf[i] = Rx_buf[i];
*proto = (Protocol *)Tx_buf;
Make_ack(proto, Rx_buf, Tx_buf);
…
// Make_ack函数实现
Make_ack(proto, Rx_buf, Tx_buf)
{
…
If(proto…)
{
F_open(…);
F_lseek(&file, proto->offset); //此处出错
F_read(…);
F_close(…);
}
…
}
就这么一段程序,从逻辑上看任何问题没有,但是就是读取不到文件,把我气得呀!还以为是文件系统出错了,就开始找文件系统的代码,结果发现没有问题。还作了测试。
然后我就怀疑是输入参数错了,挂wpe截获发送的数据,发现发送的数据完全正确,写测试代码发现接受的数据完全正确。
于是乎,挂仿真器,并用串口输出调试信息。
代码修改如下:
// Make_ack函数实现
Make_ack(proto, Rx_buf, Tx_buf)
{
…
If(proto…)
{
f_open(…);
f_lseek(&file, proto->offset); //此处出错
f_read(…);
f_close(…);
}
#ifdef OUTPUT_DEBUG_STRING
SerialPrintf(“proto->offset:%d”, proto->offset);
#endif
…
}
结果调试运行结果:在调试到proto->offset时显示的数据为0,是我预期的结果,但是串口打印的数据确是:12636928。我一看傻眼了,还有这么邪门。然后我就调试到f_lseek函数内部,发现参数传进来就给我改了地址了。呵呵,终于找到原因了,可是他娘的是怎么回事呢?然后我就琢磨着可能是四字节没有对齐,于是乎就打开了memory,发现果然Tx_buf的起始位置是四字节的中间,找编译器的设置也没找到,只要做了如下修改*proto = (Protocol *)Tx_buf;修改为*proto = (Protocol *)Rx_buf;反正数据一样。
问题解决,搞定。但是还是很不爽。