**(iptr+3)iptrが配列ポインタの場合、との間に違いはありますか*iptr[3]
5 に答える
いいえ、そして、驚くべきことに(またはそうではない)、これも。と同等*(3[iptr])です。
どちらも同じです。コンパイラはiptr[3]andをとして3[iptr]のみ扱います。*(iptr+3)*(3+iptr)
int a[5][10] = {0};この2次元配列を考えてみましょう。ここでa[i][j]はを意味する*(*(a+i) + j)ので、のように書くことi[a][j]もできます*(*(i + a) + j)。
しかしi[j][a]、それは間違っているものとして扱われるので、*(*(i + j)+a)間違っています。*(i+j)クラッシュ(未定義動作)につながります。
ポインタ演算のためも同じです。
カスタムタイプがあるとします
typedef struct
{
/* add some parameters here */
} MyStruct;
そして、このタイプのベクトルを作成します
MyStruct xMyStructArray[20];
たとえば、3番目の要素にアクセスする場合は、次のいずれかの方法でアクセスできます。
MyStruct xValue = xMyStructArray[2]; // index starts from zero
MyStruct xValue = xMyStructArray + 2;
xMyStructArrayだけが、最初の配列要素へのポインターと見なされます。
xMyStructArray ==&(xMyStructArray [0])
C / C ++は、連続するメモリセルに配列を作成し、[]演算子を使用すると、最初の配列要素アドレスに対応するポインタアドレスから開始して、その配列のそれぞれのセルにアクセスするように指示します。だからそれはあなたのタイプのサイズを知っていて、正しいアドレスに行きます。
ポインタ演算も同じように機能します。1をポインタに合計すると、コンパイラはそのポインタに対応する型のサイズをチェックし、その型と互換性のあるメモリ内の次の位置に移動します。
**(iptr+3)と*iptr[3]以来、同じものは何もありません
*iptr[3]配列内のアドレス番号3の要素を表すポインタです。
**(iptr+3) そしてそれはiptrがその**(6)より3である場合のようです
コンパイラにとっては、違いはありません。どちらのフォームも同じ要素にアクセスすることになります。
ただし、コンパイラのコードを記述している場合は、対象者が間違っています。あなたのコードは、それを維持する次の人があなたがどこに住んでいるかを知っているサイコパスであるかのように書かれるべきです。
言い換えれば、可読性と保守性のためのコードであり、コンパイラー自体に最適化について心配させます(a)。そのためには、前者が意図を明確にしているため、私は常にarray[index]形式よりも形式を好み*(array+index)ます。つまり、配列要素へのアクセスです。
(a)もちろん、ほとんどのルールと同様に、例外があります。しかし、ほとんどの例外と同様に、それらはごくわずかであり、その間にあるため、アドバイスは有効です。