2011-12-28 4 views
0

このコードを-DPORTABLEでコンパイルすると何が問題になりますか?gcc 4.3.4構造サイズの不具合?

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

typedef struct { 
    unsigned char data[11]; 

#ifdef PORTABLE 
    unsigned long intv; 
#else 
    unsigned char intv[4]; 
#endif 

} struct1; 

int main() { 

    struct1 s; 

    fprintf(stderr,"sizeof(s.data) = %d\n",sizeof(s.data)); 
    fprintf(stderr,"sizeof(s.intv) = %d\n",sizeof(s.intv)); 
    fprintf(stderr,"sizeof(s) =  %d\n",sizeof(s)); 

    return 0; 
} 

私は32ビットGCCに乗る出力:

$ gcc -o struct struct.c -DPORTABLE 
$ ./struct 
sizeof(s.data) = 11 
sizeof(s.intv) = 4 
sizeof(s) =  16 
$ gcc -o struct struct.c 
$ ./struct 
sizeof(s.data) = 11 
sizeof(s.intv) = 4 
sizeof(s) =  15 

余分なバイトがから来たのか?

私はいつも11 + 4 = 15ではない16

答えて

4

何もコードに間違っていないと思いました。これらのサイズは正しいです。コンパイラは、その裁量で、structにパディングを追加することがあります。 structのサイズは、その要素を保持できるだけの大きさであることが保証されているため、その要素のサイズを追加することは、structのサイズを取得する信頼できる方法ではありません。

このようなパディングは、Alsが指摘しているように、アラインメントエラー(おそらく-DPORTABLEが有効になっている理由)と速度最適化を避けるために、要素と構造体自体を特定の境界に保つのに役立ちます。

2

これは、structure paddingによるものです。
コンパイラは、アクセス時間を最適化するために構造体に余分なパディングバイトを自由に追加できます。

これは、常にsizeofの演算子を使用し、構造体のサイズを手動で計算する必要がない理由です。

1

アライメントと呼ばれています。これは、特に、キャッシュミスを減らすために構造体の最後にパディングを追加することです。無効にする場合は、次のようなものを使用できます。

#pragma pack(push) /* push current alignment to stack */ 
#pragma pack(1)  /* set alignment to 1 byte boundary */ 

typedef struct { 
    unsigned char data[11]; 

#ifdef PORTABLE 
    unsigned long intv; 
#else 
    unsigned char intv[4]; 
#endif 
} struct1; 

#pragma pack(pop) /* restore original alignment from stack */ 
+0

ありがとうございます! – einclude