通常、これら2つの構造体の表現はまったく同じです。ただし、ユースケースに対して間違ったものを選択すると、パフォーマンスが低下する可能性があります。
たとえば、配列を使用してループ内の各要素にアクセスする必要がある場合は、次のように実行できます。
for (int i = 0; i < 3; i++)
dosomething(xvec[i]);
ただし、配列がない場合は、コードを複製する必要があります。
dosomething(x);
dosomething(y);
dosomething(z);
これはコードの重複を意味します-どちらの方向にも進むことができます。一方では、ループコードが少なくなります。一方、最近のプロセッサでは、非常にタイトなループが非常に高速になる可能性があり、コードの重複によってIキャッシュが吹き飛ばされる可能性があります。
もう1つのオプションはスイッチです。
for (int i = 0; i < 3; i++) {
int *r;
switch(i) {
case 0: r = &x; break;
case 1: r = &y; break;
case 1: r = &z; break;
}
dosomething(*r); // assume this is some big inlined code
}
これにより、i-cacheのフットプリントが大きくなる可能性は回避されますが、パフォーマンスに大きな悪影響があります。これをしないでください。
一方、コンパイラがあまり賢くない場合は、原則として、配列アクセスが遅くなる可能性があります。
xvec[0] = xvec[1] + 1;
dosomething(xvec[1]);
xvec[0]とxvec[1]は別個のものであるため、原則として、コンパイラーはxvec [1]の値をレジスターに保持できる必要があり、次の行で値を再ロードする必要はありません。ただし、一部のコンパイラは、xvec[0]とxvec[1]がエイリアスしないことに気付くほど賢くない可能性があります。この場合、個別のフィールドを使用すると、非常に高速になる可能性があります。
要するに、それはどちらかがすべての場合に速いということではありません。それはあなたがそれをどのように使うかと表現を一致させることについてです。
個人的には、xvecで動作するコードを最も自然にするものなら何でも使用することをお勧めします。せいぜい、マイクロベンチマークでしか捉えられないほど小さなパフォーマンスの違いしか生じないようなことを心配するのに、多くの人的時間を費やす価値はありません。