2

使用 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 的情况下,成员的大小加起来就是结构的大小 (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 个额外的字节是从哪里来的?

谢谢!

4

4 回答 4

2

结构被填充为 4 个字节1的整数倍,以便它们是字对齐的。http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding

也可以看看:


1正如@Mooing Duck评论的那样,这并不总是正确的:

它并不总是 4 个字节的倍数,它会(略微)根据成员而有所不同。另一方面,99% 的时间它是 4 个字节的倍数。

于 2011-11-01T17:34:25.393 回答
1

是因为对齐。在您的平台上 uint32_t 需要 4 字节对齐。为了实现 dest_addr_64_h 必须在其前面有两个字节的填充,因为两个 uint8_t 成员之后的位置是 2 的倍数,但不是 4。

您可以使用宏 offsetof() 来确定成员在结构中的确切位置,看看这是真的。

您可以尝试使编译器将成员更紧密地打包在一起,或者您可以重新排列成员以便不需要填充。

于 2011-11-01T17:40:14.657 回答
0

数据类型根据平台有不同的对齐要求。额外的字节用于将结构的成员之一对齐到特定的大小和/或位置。如果您需要更精确的控制,您可以使用__attribute__或指定此对齐方式#pragma pack

于 2011-11-01T17:35:41.987 回答
0

您需要向编译器声明以打包结构

我相信这将适用于 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 
于 2011-11-01T17:38:14.810 回答