変数の順序だけではありません。あなたは決して使用s1せず、コンパイラは単純にそれを最適化し、スタックにスペースを割り当てません。
aあなたのようにとのアドレスだけを印刷しようとするとb、次のようになります。
ffeb7448 (&a)
ffeb7444 (&b)
つまり、4 バイトの違いです。
のアドレスも出力しようとすると、次のようになりますs1(したがって、宣言を使用s1することになります)。
ffe109cc (&a)
ffe109c8 (&s1)
ffe109c4 (&b)
a実際にはとb今回の間にあることがわかります(他の回答がすでに指摘しているように、必ずしもそうである必要はありません)。aとbは 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
これでわかることは、コードを書くときに、幅、配置、相対位置などに関連するものを決して想定しないことです。