2

いくつかの構造の場合splab:

int main() {

   int a;
   struct splab *s1;
   int b;

   printf("%x\n",&a);
   printf("%x\n",&b);

   return 0;
 }

私は 2 番目のプリントを取得する必要があると思いますbfc251e8 - 8(つまり、によって占められたスペースを説明しますs1)。

代わりに、私は得ました:

bfc251e8
bfc251ec

なんで?

4

3 に答える 3

5

変数の順序だけではありません。あなたは決して使用s1せず、コンパイラは単純にそれを最適化し、スタックにスペースを割り当てません。

aあなたのようにとのアドレスだけを印刷しようとするとb、次のようになります。

ffeb7448 (&a)
ffeb7444 (&b)

つまり、4 バイトの違いです。

のアドレスも出力しようとすると、次のようになりますs1(したがって、宣言を使用s1することになります)。

ffe109cc (&a)
ffe109c8 (&s1)
ffe109c4 (&b)

a実際にはとb今回の間にあることがわかります(他の回答がすでに指摘しているように、必ずしもそうである必要はありません)。abは 4 ではなく 8 バイトで区切られています。


わずかに関連するもう 1 つのポイントは、配置に関係しています。

例えば:

struct foo
{
  int a;
  char b;
};

この構造体は、4 バイト整数のマシンでは 5 バイト幅のように見えますが、私のコンパイラはsizeof (struct foo) == 8.

これは、fooが常に 8 バイト境界で整列されるようにするためです (これには、struct fooローカル変数の使用が含まれます)。

例えば

int bar (void)
{
  struct foo a;
  struct foo b;

  /* Do some work.  */
}

ここでは、aとは、実際にはそれぞれ 5 バイトしか使用しbていませんが、私のマシンのコンパイラでは 8 バイトで区切られています。foo

これでわかることは、コードを書くときに、幅、配置、相対位置などに関連するものを決して想定しないことです。

于 2012-07-02T11:49:28.260 に答える
2

コンパイラーはスタック上の変数の位置を自由に並べ替えることができるため、ポインターが途中で宣言されていても、変数がポインターのb前に来る可能性があります。s1

このような再配置により、一部のデータタイプでは調整が必要になるため、メモリ使用率が向上し、ギャップの可能性がなくなります。

于 2012-07-02T11:35:01.893 に答える
1

ポインタがメモリを使用する量によって変化する必要があるアドレスとの間でポインタs1が割り当てられたからですか?(私にはよくわかりませんでした)。ab

もしそうなら、これを当てにすることはできないと思います。異なる変数間でメモリがどのように割り当てられるかは、あなたの制御下にはありません。メモリは直線的に割り当てられているように見えるかもしれませんが、信頼できるものではありません。

あなたの質問の解釈が間違っていたら/言い換えて/明確にしてもらえますか?

于 2012-07-02T11:31:22.020 に答える