2009-08-25 27 views
9

のための直接のメンバーへのアクセスは、私は次のよう...Cポインタ対構造体

typedef struct { 
    int WheelCount; 
    double MaxSpeed; 
} Vehicle; 

のような構造体を持っていると言う...と私は、このタイプのグローバル変数を持っています私が設計していない組み込みシステムのためのものであり、それは不幸なことですが必要な悪です)。構造体のメンバーに直接またはポインタでアクセスする方が速いのですか?つまりは、私の仕事の

double LocalSpeed = MyGlobal.MaxSpeed; 

または

double LocalSpeed = pMyGlobal->MaxSpeed; 

一つは、簡素化し、最近では継承された組み込みシステムを修正することです。

+1

ポインタは、直接アクセスでは何を提供しますか?ポインタが遅いです。 –

+3

-1は、最初にベンチマークすることなくマイクロ最適化について質問します。 – bk1e

答えて

19

一般的に、私は最初のオプションで行くと言うだろう:

double LocalSpeed = MyGlobal.MaxSpeed; 

この1つの少ない間接参照を(あなたはそれが場所だし、それは取得するには逆参照、ポインタを見つけていない)があります。構造体に加えてポインタ変数を作成する必要がないので、読み込みと保守も簡単で簡単です。

言われているように、私は組み込みシステム上でさえ目に見えるようなパフォーマンスの違いはないと思います。どちらも非常に高速なアクセス時間になります。

+0

なぜdownvotes?私は人々がなぜ同意しないのか不思議に思います。 –

+1

私はここにリードと一緒です。直接参照はより安全で、NULLチェックを必要とせず、逆参照操作を保存します。変数のメモリ内容は、とにかくアクセスする必要があります。なぜ、追加ルックアップを行うのですか? すでに変数に直接アクセスしている場合は、ポインタは何も得られません。 –

+0

ポインタ逆参照については、それは私が考えていたものです.CまたはC++のどちらかに対処しなければならなかったので、これは長いことです。皆さん、アドバイスをいただきありがとうございます。 –

1

これがまったく違うとすれば、それはアーキテクチャに依存すると思います。

1

Cでは、違いがないか、パフォーマンスに大きな差がないはずです。

Cの生徒が教えられています:

pMyGlobal->MaxSpeed == (*pMyGlobal).MaxSpeed 

あなたは、彼らはあなたがアセンブリコードプログラマでない場合でも、基本的に同じであることを自分自身を納得させるために、それらの両方の分解を比較することができるはずです。

パフォーマンスの最適化をお探しの場合は、別の場所を探します。この種のマイクロ最適化では、十分なCPUサイクルを節約することはできません。

私は文章上の理由から、特にシングルトン・グローバルを扱うときは構造ドット記法を好んでいます。私はそれを読むのがはるかにきれいだと思う。

+1

質問は - > vs *についてではなく、最初はポインタを使うことです。 –

+1

質問は次のとおりです。 "構造体のメンバーに直接またはポインタを介してアクセスする方が速いのですか?"私はその質問に対処したと信じています。 – abelenky

8

ポインタの逆参照を必要としないため、最初の方が高速になります。 x86システムの場合も同様ですが、他のものはわかりません。

x86で最初のものは、この

mov eax, [address of MyGlobal.MaxSpeed] 

のようなものに変換します2つ目は、一般的には、この

mov ebx, [address of pMyGlobal] 
mov eax, [ebx+sizeof(int)] 
1

ようになり、直接構造体へのアクセスは速くなり、など余分なポインタ逆参照を必要としません。ポインタ逆参照とは、ポインタ(変数の中のもの)をとり、それが指しているものをロードし、それを操作しなければならないことを意味します。あなたの組み込みプラットフォーム上で

3

は、それはアーキテクチャが、それは本質的な洗浄だように最適化され、これは非常にタイトなループ内で実行された場合、それがなかった場合でも、あなたが唯一のこれまでのパフォーマンスへの影響に気づくであろうと考えられます。

お使いのシステムのおそらくはるかに明白なパフォーマンスエリアがあります。

3
struct dataStruct 
{ 
    double first; 
    double second; 
} data; 

int main() 
{ 
    dataStruct* pData = &data; 

    data.first = 9.0; 
    pData->second = 10.0; 
} 

これはVS2008のリリースモード使用してアセンブリの出力である:

data.first = 9.0; 
008D1000 fld   qword ptr [[email protected] (8D20F0h)] 

    pData->second = 10.0; 
008D1006 xor   eax,eax 
008D1008 fstp  qword ptr [data (8D3378h)] 
008D100E fld   qword ptr [[email protected] (8D20E8h)] 
008D1014 fstp  qword ptr [data+8 (8D3380h)] 
+1

彼の組み込みプラットフォームをターゲットにしましょう。 – Alan

+0

最適化設定は何ですか? –

+0

これは間違っています。あなたの最初のメンバーは常に構造体の定義によって勝ちます(構造体のポインタもまた最初のメンバーのポインタです)。 2番目と2番目を比較する必要があります。 –

2

を逆アセンブル、逆アセンブル、逆アセンブル...

コードの行に応じて、あなたはそれが可能である私たちに表示されませんあなたのポインタが多少静的であれば、良いコンパイラはそれを知っていて、両方のアドレスをあらかじめ計算しておくでしょう。あなたが最適化をしていなければ、この全体的な議論はミュートです。また、使用しているプロセッサーによって異なりますが、どちらもプロセッサーに応じて1つの命令で実行できます。だから私は、基本的な最適化の手順に従います。

1)一番下の行は、それが2つの命令の場合の代わりに、単一クロックの原価計算であってもよいですが、上述したように実行

)時間を分解し、 2を調べますあなたは決して見えないだろう。コンパイラとオプティマイザの選択肢の品質は、パフォーマンスを向上させるためにコードの1行を微調整しようとするよりもはるかに劇的なパフォーマンスの違いになります。コンパイラを切り替えることで、どちらの方向にも10〜20%、場合によってはそれ以上のものが得られます。最適化フラグを変更することができますが、すべての処理を行わないとコードが最速になります。-O1は-O3よりも優れていることがあります。コードの生産とどのようにこれらの2行は、高レベルの言語からのパフォーマンスを最大化するためにどのような理解

異なるプロセッサ用にコンパイルすると、様々なコンパイラを使用して分解するから来ています。さらに重要なことは、問題の行のコードは、コンパイラがそのセグメントをどのように最適化するかに大きな役割を果たします。 GCC(ないその偉大コンパイラ)で

typedef struct 
{ 
    unsigned int first; 
    unsigned int second; 
} dataStruct; 

dataStruct data; 

int main() 
{ 
    dataStruct *pData = &data; 

    data.first = 9; 
    pData->second = 10; 

    return(0); 
} 

あなたが得る:この質問に誰かの例を使用して

mov r2, #10 
mov r1, #9 
stmia r3, {r1, r2} 

Cコードのだから、両方の行を1つのストアに結合され、ここでの問題は、テストとして使用される例です。二つの別々の機能が少し良くなっているだろうが、それはそれの周りに多くのコードを必要とし、ポインタがオプティマイザのdoesntのようにいくつかの他のメモリを指す必要があります内のアドレスを渡す必要があり、これをテストするために、それは静的なグローバルアドレスで実現コンパイラ(よくgcc)は静的アドレスであることを理解できません。

またはNO最適化、同じコード、同じコンパイラ、ポインタと直接間に差を有します。

mov r3, #9 
str r3, [r2, #0] 

mov r3, #10 
str r3, [r2, #4] 

これはコンパイラとプロセッサによって表示されることが予想されるものですが、違いはありません。このプロセッサでは、たとえテストコードが関数からポインタの静的アドレスを隠していたとしても、それはまだ2つの命令に沸きます。構造体要素に格納されている値がすでにレジスタにロードされている場合は、way、pointerまたはdirectのいずれかの命令になります。

だからあなたの質問への答えは絶対的ではありません...場合によります。分解してテストしてください。

+0

intの代わりに倍精度を使用すると、ストア自体がポインタまたは直接アクセスのための単一の命令であるため、このコンパイルセッションのこのプロセッサのこのコンパイラには違いはありません。 –

+0

これは間違っています。あなたの最初のメンバーは常に構造体の定義によって勝ちます(構造体のポインタもまた最初のメンバーのポインタです)。 2番目と2番目を比較する必要があります。 –

0

直接メンバーへのアクセスは高速です(ポインタの逆参照操作は通常より多くなります)。私は、それが問題、パフォーマンス、または他の状況になる状況でそれを想像するのは難しいですが。

関連する問題