使用stdint.h库中的uint32_t类型时遇到问题。如果我运行以下代码(在Ubuntu linux 11.10 x86_64,g ++版本4.6.1):
#include "stdint.h"
#include <iostream>
using std::cout;
typedef struct{
// api identifier
uint8_t api_id;
uint8_t frame_id;
uint32_t dest_addr_64_h;
uint32_t dest_addr_64_l;
uint16_t dest_addr_16;
uint8_t broadcast_radius;
uint8_t options;
// packet fragmentation
uint16_t order_index;
uint16_t total_packets;
uint8_t rf_data[];
} xbee_tx_a;
typedef struct{
// api identifier
uint8_t api_id;
uint8_t frame_id;
uint16_t dest_addr_64_h;
uint16_t dest_addr_64_l;
uint16_t dest_addr_16;
uint8_t broadcast_radius;
uint8_t options;
// packet fragmentation
uint16_t order_index;
uint16_t total_packets;
uint8_t rf_data[];
} xbee_tx_b;
int main(int argc, char**argv){
xbee_tx_a a;
cout<<"size of xbee_tx_a "<<sizeof (xbee_tx_a)<<std::endl;
cout<<"size of xbee_tx_a.api_id "<<sizeof (a.api_id)<<std::endl;
cout<<"size of xbee_tx_a.frame_id "<<sizeof (a.frame_id)<<std::endl;
cout<<"size of xbee_tx_a.dest_addr_64_h "<<sizeof (a.dest_addr_64_h)<<std::endl;
cout<<"size of xbee_tx_a.dest_addr_64_l "<<sizeof (a.dest_addr_64_l)<<std::endl;
cout<<"size of xbee_tx_a.dest_addr_16 "<<sizeof (a.dest_addr_16)<<std::endl;
cout<<"size of xbee_tx_a.broadcast_radius "<<sizeof (a.broadcast_radius)<<std::endl;
cout<<"size of xbee_tx_a.options "<<sizeof (a.options)<<std::endl;
cout<<"size of xbee_tx_a.order_index "<<sizeof (a.order_index)<<std::endl;
cout<<"size of xbee_tx_a.total_packets "<<sizeof (a.total_packets)<<std::endl;
cout<<"size of xbee_tx_a.rf_data "<<sizeof (a.rf_data)<<std::endl;
cout<<"----------------------------------------------------------\n";
xbee_tx_b b;
cout<<"size of xbee_tx_b "<<sizeof (xbee_tx_b)<<std::endl;
cout<<"size of xbee_tx_b.api_id "<<sizeof (b.api_id)<<std::endl;
cout<<"size of xbee_tx_b.frame_id "<<sizeof (b.frame_id)<<std::endl;
cout<<"size of xbee_tx_b.dest_addr_64_h "<<sizeof (b.dest_addr_64_h)<<std::endl;
cout<<"size of xbee_tx_b.dest_addr_64_l "<<sizeof (b.dest_addr_64_l)<<std::endl;
cout<<"size of xbee_tx_b.dest_addr_16 "<<sizeof (b.dest_addr_16)<<std::endl;
cout<<"size of xbee_tx_b.broadcast_radius "<<sizeof (b.broadcast_radius)<<std::endl;
cout<<"size of xbee_tx_b.options "<<sizeof (b.options)<<std::endl;
cout<<"size of xbee_tx_b.order_index "<<sizeof (b.order_index)<<std::endl;
cout<<"size of xbee_tx_b.total_packets "<<sizeof (b.total_packets)<<std::endl;
cout<<"size of xbee_tx_b.rf_data "<<sizeof (b.rf_data)<<std::endl;
}
然后我得到以下输出:
size of xbee_tx_a 20
size of xbee_tx_a.api_id 1
size of xbee_tx_a.frame_id 1
size of xbee_tx_a.dest_addr_64_h 4
size of xbee_tx_a.dest_addr_64_l 4
size of xbee_tx_a.dest_addr_16 2
size of xbee_tx_a.broadcast_radius 1
size of xbee_tx_a.options 1
size of xbee_tx_a.order_index 2
size of xbee_tx_a.total_packets 2
size of xbee_tx_a.rf_data 0
----------------------------------------------------------
size of xbee_tx_b 14
size of xbee_tx_b.api_id 1
size of xbee_tx_b.frame_id 1
size of xbee_tx_b.dest_addr_64_h 2
size of xbee_tx_b.dest_addr_64_l 2
size of xbee_tx_b.dest_addr_16 2
size of xbee_tx_b.broadcast_radius 1
size of xbee_tx_b.options 1
size of xbee_tx_b.order_index 2
size of xbee_tx_b.total_packets 2
size of xbee_tx_b.rf_data 0
我正在做的是打印出结构的总大小和结构的每个成员的大小。
在xbee_tx_b的情况下,成员的大小加起来为struct的大小(14)
在xbee_tx_a的情况下,成员的大小加起来为18个字节......但结构的大小是20个字节!
xbee_tx_a和xbee_tx_b之间的唯一区别在于dest_addr_64_X成员的类型。它们是xbee_tx_a中的uint32_t和xbee_tx_b中的uint16_t。当我使用uint32_t时,为什么结构的大小大于其成员大小的总和?这2个额外字节来自哪里?
谢谢!
答案 0 :(得分:2)
结构被填充为4字节 1 的整数倍,因此它们是字对齐的。 http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding
另见:
1 正如@Mooing Duck所述,这不是总是是真的:
它并不总是4个字节的倍数,它会根据成员的不同而略有不同。另一方面,99%的时间是4字节的倍数。
答案 1 :(得分:1)
这是因为对齐。在您的平台上,uint32_t需要4字节对齐。为了实现这一点,dest_addr_64_h必须在它前面有两个填充字节,因为两个uint8_t成员之后的位置是2的倍数但不是4的。
您可以使用宏offsetof()来确定成员在结构中的确切位置,以确定这是真的。
您可以尝试让编译器将成员组合在一起,也可以重新排列成员,以便不需要填充。
答案 2 :(得分:0)
数据类型具有基于平台的不同对齐要求。额外字节用于将结构中的一个成员与特定大小和/或位置对齐。如果您需要更精确的控制,可以使用__attribute__
或#pragma pack
答案 3 :(得分:0)
您需要向编译器声明打包结构
我相信这适用于GCC
struct test
{
unsigned char field1;
unsigned short field2;
unsigned long field3;
} __attribute__((__packed__));
在MS中,这将是使用pragma packed
的东西http://www.cplusplus.com/forum/general/14659/
#pragma pack(push, 1) // exact fit - no padding
struct MyStruct
{
char b;
int a;
int array[2];
};
#pragma pack(pop) //back to whatever the previous packing mode was