4

整数型の2つのメンバーを持つ構造体について考えてみます。両方のメンバーを住所で取得したい。最初のものは正常に取得できますが、2番目のものでは間違った値を取得しています。それがゴミの価値だと思います。これが私のコードです:

#include <stdio.h>

typedef struct { int a; int b; } foo_t;

int main(int argc, char **argv)
{

  foo_t f;
  f.a = 2;
  f.b = 4;
  int a = ((int)(*(int*) &f));
  int b = ((int)(*(((int*)(&f + sizeof(int)))))); 
  printf("%d ..%d\n", a, b);
  return 0;
}

私が得ている:

2..1

誰かが私がどこで間違っているのか説明できますか?

4

5 に答える 5

7

C 標準では、最初のメンバーのオフセットは常に 0 でなければなりません。そのため、最初のキャストが機能します。ただし、2 番目のメンバーのオフセットは、パディングのため、必ずしも構造体の最初のメンバーのサイズと同じであるとは限りません。

さらに、ポインタに数値を追加しても、アドレスにバイト数は追加されません。代わりに、ポイントされているもののサイズが追加されます。したがって、 に追加sizeof(int)すると&fsizeof(int)*sizeof(foo_t)が追加されます。

offsetof自分で計算したい場合は、次のように演算子を使用できます

int b = *((int*)(((char*)&f)+offsetof(foo_t, b)));

これが機能する理由は、C 標準で要求されているように、常に 1 であるためsizeof(char)です

もちろん&f.b、手動で計算を行うことを避けるために使用できます。

于 2012-12-31T03:12:54.623 に答える
2

あなたの問題は&f + sizeof(int). Aがポインタで、かつBが整数の場合、CではプラスバイトA + Bを意味しません。むしろ、要素のサイズが のポインター型によって定義されるプラス要素を意味します。したがって、お使いのアーキテクチャで が 4の場合、 「4が に、または 4 * 8 = 32 バイトが」という意味になります。ABABAsizeof(int)&f + sizeof(int)foo_t&f&f

((char *)&f) + sizeof(int)代わりに試してください。

または、もちろん、&f.a代わり&f.bに、非常に単純です。後者は、とにかく便利なintポインターを提供し、それらすべてのキャストから解放されるだけでなく、明確に定義され、理解しやすいものになります。:)

于 2012-12-31T03:13:30.867 に答える
2

この式&f + sizeof(int)は、型 のポインターに数値を追加しますfoo_t*。ポインター演算では、常にポインターが配列の要素を指していると想定し、数値は要素の数として扱われます。

したがって、sizeof(int)が 4 の場合、構造体の4 つ後、または のバイト先を&f + sizeof(int)指します。foo_tf4*sizeof(foo_t)&f

バイト カウントを使用する必要がある場合は、次のようなものが機能する可能性があります。

int b = *(int*)((char*)(&f) + sizeof(int));

a...メンバーとの間にパディングがないと仮定しますb

f.bしかし、値やポインターを取得しない理由はあります&f.bか?

于 2012-12-31T03:14:06.440 に答える
1

&f.bを実行して、実際のポインター計算をスキップできます。

これが私があなたのint b行を変更する方法です:

int b = (int)(*(((int*)(&(f.b)))));

ところで、プログラムをそのまま実行する2 ..0と、出力が得られます。

于 2012-12-31T03:12:43.607 に答える
1

これは機能します:

  int b = ((int)(*(int*)((int)&f + sizeof(int))));

&f をポインターとして解釈し、それに 4 (int のサイズ) を追加すると、32 対 64 アーチに応じて 16 または 32 バイトの 4 つのポインターを追加すると解釈されます。ポインターを int にキャストすると、適切に 4 バイトが追加されます。

これは何が起こっているかの説明です。あなたが何をしているのかはわかりませんが、そのようなことをすべきではないことは間違いありません。これにより、配置などの問題が発生する可能性があります。構造体要素のオフセットを把握する安全な方法は次のとおりです。

  printf("%d\n", &(((foo_t *)NULL)->b));
于 2012-12-31T03:13:06.557 に答える