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 の直前に 2 バイトのパディングが必要です。これは、2 つの uint8_t メンバーの直後の位置が 2 の倍数であり、4 ではないためです。

マクロ offsetof() を使用して、メンバーが構造体内のどこに配置されているかを正確に把握し、これが正しいことを確認できます。

コンパイラがメンバーをより緊密にパックするようにするか、パディングが不要になるようにメンバーを再配置することができます。

于 2011-11-01T17:40:14.657 に答える
0

データ型には、プラットフォームに基づいて異なる整列要件があります。余分なバイトは、構造体のメンバーの 1 つを特定のサイズや位置に揃えるために使用されます。より正確な制御が必要な場合は、この配置を__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では、プラグマパックを使用したものになります

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 に答える