他の誰もそれを理解して維持することができないので、コードが投げられてもコードがどれほど速いかは問題ではありません。また、トリッキーなコードは、コンパイラがより良い最適化を行うのを妨げる場合があります。
例えば:
int main(void)
{
int arr[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
int *p = *arr; // == arr[0] == &arr[0][0]
int x;
x = arr[2][3]; // Straightforward array access
x = *(*(arr+2)+3); // Ugly pointer arithmetic
x = *(ptr + 11); // Slightly less ugly pointer arithmetic
return 0;
}
上記を実行してgcc -c -g -Wa,-a,-ad > foo.lst
、生成されたアセンブリとソースコードをインターリーブしました。
これがの翻訳ですx = arr[2][3];
:
movl -16(%ebp), %eax
movl %eax, -8(%ebp)
これがの翻訳ですx = *(*(arr+2)+3);
:
leal -60(%ebp), %eax
addl $44, %eax
movl (%eax), %eax
movl %eax, -8(%ebp)
そして最後に、x = *(ptr + 11);
:の翻訳
movl -12(%ebp), %eax
addl $44, %eax
movl (%eax), %eax
movl %eax, -8(%ebp)
コンパイラの裏をかくことを試みないでください。これはもう1970年代ではありません。gccは、ユーザーに指示しなくても、配列アクセスを効率的に実行する方法を知っています。
アルゴリズムとデータ構造を調整し、コンパイラで最高の最適化設定を使用し(FWIW、3つのバージョンすべてで同じコードを生成する)、それでも失敗しない限り、このレベルでのパフォーマンスについて考える必要はありません。厳しいパフォーマンス要件を満たすため(この場合、正しい答えは通常、より高速なハードウェアを購入することです)。また、最初にプロファイラーを介してコードを実行し、実際のボトルネックを見つけることなく、 何も変更しないでください。測定、推測しないでください。 -O1
編集
当然、リテラル2
と3
が変数に置き換えられると、状況が変化します。その場合、*(ptr + offset);
見栄えが良くなります。しかし、それほどではありません。そして、私はまだ、このレベルでは明快さがより重要であると主張します。