2011-12-15 17 views
7

ここ質問Cポインタ演算はsizeof(構造体)

#include <stdio.h> 

struct test { 
    unsigned char t; 
    unsigned short u; 
    unsigned char v; 
}; 


int main() 
{ 
    struct test * a = (void *) 0x1000; 

    printf("%x %p %p\n", 
      sizeof(struct test), 
      a + sizeof(struct test), 
      a - sizeof(struct test)); 

    return 0; 
} 

のコードはsizeof(構造体試験)6を印刷するので、私はが見て期待されます代わりに私は得る

6 0x1024 0xfdc 

前回Ic 0x24、または36であり、6に等しくはありませんでした。私は完全に迷っています。

誰かが私にこれらの値を得ている理由を説明してもらえますか?

答えて

16

問題は、ポインタの算術演算を行うときに、データ型のサイズがので増分することです。

あなたが効果的にやっていることは、sizeof(struct test)の四角で足し算することです。

sizeof(struct test) = 6以降、住所は6 * 6 = 36で増えています。なぜ0x10060xffaの代わりに0x10240xfdcが得られるのですか?私はあなたがa + 1a - 1を探していると思う

printf("%x %p %p\n", 
     sizeof(struct test), 
     a + 1, 
     a - 1); 
1

入力ポインタがあります。

したがって、1を増やすと(a + 1)、それはa + sizeof(type)を意味します。あなたから0x24または36を取得しているところだ

のでa + sizeof(type) = a + sizeof(type) * sizeof(type) = a + 6 * 6(あなたのケースではsizeofなど(テスト)= 6)

2

:(。また+-を切り替え、それは小さなことだ)

を代わりに、ちょうどこれを行います。

(a + x)は、&a[x]と同じです。

+2

'*(a + x)'は 'a [x]'と同じか、 '(a + x)'は '&a [x]'と同じであると言いたいでしょう。 –

4

このようなポインタの算術演算を行うと、その変数が配列にあるかのように、その要素数だけ前進または後退します。したがって、実際にはa + 1a - 1を使用する必要がありますが、そのたびに6バイトずつ進む必要があります。

重要:コンパイラは、整列に役立つように構造体にパディングを追加できることに注意してください。 2バイトの1バイト文字と2バイトのshortがあり、構造体のサイズが4バイトであるため、これは仮定しないでください。これはここでは当てはまりません。 (実際には、charまたはshortのサイズを知っていると仮定しない;前に2バイトのcharを見たことがある)。

+3

実際、それはかなり正確ではありません。配列要素の間にパディングを追加することはできません。それができるのは、構造体の要素の間と構造体の最後の要素の後ろにあるパッドです(これはおそらくあなたが参照しているビットです)。しかし、構造体自体は、整列要件がある場合には正しいサイズになるように埋められます。ここでは6バイトはおそらく 'char(1)、pad(1)、short(2)、char(1)、pad(1)'です。最後のパディングは単一の構造体要素に属しますが、その構造体で構成された配列内の要素ではありません。 Nitpickモードオフ:-) – paxdiablo

+1

ありがとう、私はC99の仕様を振り返って私の応答をrewordしました。 –

関連する問題