分解、分解、分解…
表示されていないコード行によっては、ポインターがある程度静的である場合、優れたコンパイラーがそれを認識し、両方のアドレスを事前に計算する可能性があります。最適化を行っていない場合、この議論全体は無言です。また、使用しているプロセッサにも依存します。プロセッサによっては、両方を 1 つの命令で実行できます。したがって、基本的な最適化手順に従います。
1) 分解して調べる 2) 実行時間を計る
上で述べたように、肝心なのは、1 つのクロック サイクルがかかるのではなく、2 つの命令の場合である可能性があるということです。コンパイラーとオプティマイザーの選択の質によって、パフォーマンスの向上を期待して 1 行のコードを微調整するよりもはるかに劇的なパフォーマンスの違いが生まれます。コンパイラを切り替えると、どちらの方向でも 10 ~ 20%、場合によってはそれ以上の結果が得られます。最適化フラグを変更できるように、すべてをオンにしてもコードが最速になるわけではなく、-O1 が -O3 よりもパフォーマンスが優れている場合があります。
これら 2 行のコードが生成するものと、高水準言語からパフォーマンスを最大化する方法を理解するには、さまざまなプロセッサ用にコンパイルし、さまざまなコンパイラを使用して逆アセンブルします。さらに重要なことに、問題の行の周りのコードは、コンパイラがそのセグメントを最適化する方法に大きな役割を果たします。
この質問で他の人の例を使用する:
typedef struct
{
unsigned int first;
unsigned int second;
} dataStruct;
dataStruct data;
int main()
{
dataStruct *pData = &data;
data.first = 9;
pData->second = 10;
return(0);
}
gcc (それほど優れたコンパイラではない) を使用すると、次のようになります。
mov r2, #10
mov r1, #9
stmia r3, {r1, r2}
したがって、C コードの両方の行が 1 つのストアに結合されます。ここでの問題は、テストとして使用される例です。2 つの別個の関数の方が少しはましでしたが、その周りにはさらに多くのコードが必要であり、ポインタは他のメモリを指す必要があるため、オプティマイザはそれが静的グローバル アドレスであることを認識しません。これをテストするには、アドレスを渡す必要があります。そのため、コンパイラ (まあ gcc) はそれが静的アドレスであることを認識できません。
または、最適化なし、同じコード、同じコンパイラ、ポインターと直接の違いなし。
mov r3, #9
str r3, [r2, #0]
mov r3, #10
str r3, [r2, #4]
これは、コンパイラとプロセッサに応じて表示されると予想されるものであり、違いがない場合があります。このプロセッサでは、テスト コードがポインタの静的アドレスを関数から隠していたとしても、2 つの命令に要約されます。構造要素に格納されている値が既にレジスタにロードされている場合、ポインターまたは直接のいずれかの方法で 1 つの命令になります。
したがって、あなたの質問への答えは絶対的なものではありません...それは依存します. 分解してテスト。