0

C の構造パディングについてこれを読みました: http://bytes.com/topic/c/answers/543879-what-structure-padding 記事の後にこのコードを書きました。 16 バイトのように、「struct pad2」のサイズは 12 にする必要があります。このコードをさまざまなレベルの最適化を使用して gcc でコンパイルしました。 sizeof() 演算子でさえ、両方とも 16 バイトになります。それはなぜです?

この情報は、バイト境界と完全な dma 転送の活用が重要な PS3 マシンのために必要です。

#include <stdio.h>
#include <stdlib.h>

struct pad
{
    char  c1;  // 1 byte
    short s1;  // 2 byte
    short s2;  // 2 byte
    char  c2;  // 1 byte
    long  l1;  // 4 byte
    char  c3;  // 1 byte
};

struct pad2
{
    long  l1;
    short s1;
    short s2;
    char  c1;
    char  c2;
    char  c3;
};

int main(void)
{
    struct pad P1;
    printf("%d\n", sizeof(P1));

    struct pad P2;
    printf("%d\n", sizeof(P2));

    return EXIT_SUCCESS;
}
4

6 に答える 6

4

この問題を克服するために使用できる 2 つのトリックがあります。

  1. ディレクティブ #pragma pack(1) と #pragma pack(pop) の使用例:

    #pragma pack(1)
    
    struct tight{           
       short element_1;       
       int *element_2;
    };
    #pragma pack(pop) 
    
  2. コンパイル中に 2 つの構造体のサイズが同じかどうかを確認するには、このトリックを使用します。

    char voidstr[(sizeof(struct1)==sizeof(struct2)) - 1]; //it will return error at compile time if this fail
    
于 2009-08-01T18:29:55.817 に答える
4

構造にはそれぞれ が含まれておりlong、これは明らかにプラットフォームで 4 バイト境界にある必要があります。構造体は、少なくとも最もアラインされたメンバーと同程度にアラインされている必要があるため、4 バイトでアラインされている必要があり、構造体のサイズは配列に入る場合にアラインメントの倍数である必要があります。

整列させるには追加のパディングが必要なlongため、最小の 4 の倍数は 16 です。

2 つのアドバイス:

  • l1フィールドのオフセットは次のように計算できます。

     printf("Offset of field %s is %d\n", "l1", offsetof(struct pad, l1);
    

    マクロを取得するには、offsetof必要があります#include <stddef.h>(caf に感謝します!)。

  • データをできるだけ高密度にパックしたい場合は、unsigned char[4]の代わりにと をlong使用し、演算を行って変換します。unsigned char[2]short


編集::sizeof(struct pad2) 12 です。コードにはバグがあります。構造体P2は type で宣言されていstruct padます。これを試して:

#define xx(T) printf("sizeof(" #T ") == %d\n", sizeof(T))
  xx(struct pad);
  xx(struct pad2);

PS私は真夜中以降にSOの質問に答えようとするのを絶対にやめるべきです.

于 2009-08-01T01:52:05.580 に答える
1

すべての CPU は、(int、float、char、double) のような組み込みのデータ型が、それらの長さのアドレスで、自然な境界でメモリに格納されることを期待しています。そのため、メモリからのデータへのアクセスを高速化するために、構造体のパディングが行われます。たとえば、int が宣言されている場合、メモリ内の 4 の倍数のアドレスで発生する必要があります。

int のサイズは 4 バイトです。

double の場合も同様に、8 の倍数でメモリに常駐します。

メモリが適切に配置されている場合、CPU はより高速に動作し、効率的に動作します。

次の例では、次のように仮定します。

Sizeof(int)=4 バイト

Sizeof(float)=4 バイト

Sizeof(char)=1 バイト

BoundsCheckの詳細を確認する

于 2010-06-29T18:27:11.277 に答える
1

PS3では、推測しないでください。などを使用__attribute__((aligned (16)))します。構造体の開始が適切な境界 (グローバルまたは静的の場合) に配置されることを保証するだけでなく、指定した配置の倍数になるように構造体をパディングします。

于 2009-08-01T02:17:04.927 に答える
1

P1 と P2 の両方が構造体パッドのインスタンスとして定義されているため、コードはあなたが考えているものを示していません。struct pad2 は使用されません。

P2 の定義を struct pad2 になるように変更すると、gcc は実際にサイズを 12 にすることを決定します。

于 2009-08-01T02:24:30.940 に答える
1
struct pad P1;
printf("%d\n", sizeof(P1));

struct pad P2;
printf("%d\n", sizeof(P2));

P1 と P2 は同じタイプの「struct pad」を持っています。おそらく、P2 に「struct pad2」を使用したいでしょう。

于 2009-08-01T02:27:37.113 に答える