将struct的成员声明为uint32_t时额外的字节
Extra bytes when declaring a member of a struct as uint32_t
当使用stint .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,成员的大小加起来等于结构体(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时,结构的大小大于其成员大小的总和?那两个额外的字节是从哪里来的?
谢谢!
结构被填充为4字节1的整数倍,以便它们是对齐的。http://en.wikipedia.org/wiki/Data_structure_alignment Data_structure_padding
参见:
- 为什么struct的sizeof等于每个成员的sizeof之和?
- 结构填充和包装
- 使用结构体填充
1正如@Mooing Duck评论的那样,这并不总是为真:
它并不总是4字节的倍数,它根据成员的不同(略有不同)。另一方面,99%的情况下它是4字节的倍数。
这是因为对齐。在你的平台上,uint32_t需要4字节对齐。为了实现这一点,dest_addr_64_h必须在它前面有两个字节的填充,因为在两个uint8_t成员之后的位置是2的倍数,而不是4。
您可以使用宏offsetof()来确定成员在结构体中的确切位置,以查看这是否为真。
您可以尝试让编译器将成员更紧密地打包在一起,或者您可以重新排列成员,以便不需要填充。
不同平台的数据类型有不同的对齐要求。额外的字节用于将结构的一个成员对齐到特定的大小和/或位置。如果您需要更精确的控制,您可以使用__attribute__
或#pragma pack
您需要向编译器声明打包结构
我相信这将工作在GCC
struct test
{
unsigned char field1;
unsigned short field2;
unsigned long field3;
} __attribute__((__packed__));
在MS中,它将使用打包的pragma
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
- 从不同线程使用int64的不同字节安全吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 在UNIX系统中使用DIR查找文件的字节大小
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- std::当在256字节边界上写入整数时,流的奇怪行为
- 当比特(而不是字节)的顺序至关重要时的持久性
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何在文件中查找字节序列
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 字节到位运算符重载C++
- 在java中读取c++字节的位字段
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 字节真的是最小可寻址单元吗
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- 如何使用 OpenCV 解码在两个 UWP 应用之间发送的图像字节?
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- asn1c 不会从 asn.1 模块中提取八位字节字符串的默认值
- 为什么当我使用双精度时,Qt<->Matlab 正确写入和读取我的字节,但存储 uint32 的字节不正确?
- UInt64在32位系统上,需要从UInt32's字节数组生成,如何