Extra bytes when declaring a member of a struct as uint32_t
我在使用stdint.h库中的uint32_t类型时遇到问题。如果我运行以下代码(在Ubuntu Linux 11.10 x86_64,G++版本4.6.1上):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #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<<"---------------------------------------------------------- "; 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; } |
然后我得到以下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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,成员的大小加起来等于结构的大小(14)
对于xbee-tx-a,成员的大小加起来多达18个字节…但是结构的大小是20字节!
xbee_tx_a和xbee_tx_b之间的唯一区别在于dest_addr_64_x成员的类型。它们是xbee-tx-a中的uint32,xbee-tx-b中的uint16。为什么使用uint32-t时结构的大小大于其成员大小的总和?这两个额外的字节来自哪里?
谢谢!
结构被填充为4字节1的整数倍,以便它们与字对齐。http://en.wikipedia.org/wiki/data_-structure_-alignment_data_-structure_-padding
参见:
- 为什么结构的sizeof不等于每个成员的sizeof之和?
- 结构填料和填料
- 结构填充的使用
1正如@moing duck评论的那样,这并不总是正确的:
It's not always a multiple of 4 bytes, it varies (slightly) depending on the members. On the other hand, 99% of the time it's a multiple of 4 bytes.
这是因为对齐。在您的平台上,uint32_t需要4字节对齐。为了实现这个目的,dest_addr_64_h前面必须有两个字节的填充,因为两个uint8_t成员后面的位置是2的倍数,而不是4。
您可以使用宏OffStof()来精确地确定成员放置在结构中的位置,以查看这是真的。
你可以试着让编译器把成员打包在一起,或者你可以重新安排成员,这样就不需要填充了。
需要向编译器声明以打包结构
我相信这对海湾合作委员会有效
1 2 3 4 5 6 | struct test { unsigned char field1; unsigned short field2; unsigned long field3; } __attribute__((__packed__)); |
在MS中,使用pragma packed
http://www.cplusplus.com/forum/general/14659/
1 2 3 4 5 6 7 8 | #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 |
基于平台,数据类型具有不同的对齐要求。额外的字节用于将结构的一个成员与特定的大小和/或位置对齐。如果需要更精确的控制,可以指定与