質問
次のコードがあるとします:
int main(){
int a[3]={1,2,3};
printf(" E: 0x%x\n", a);
printf(" &E[2]: 0x%x\n", &a[2]);
printf("&E[2]-E: 0x%x\n", &a[2] - a);
return 1;
}
コンパイルして実行すると、結果は次のようになります。
E: 0xbf8231f8
&E[2]: 0xbf823200
&E[2]-E: 0x2
& E [2] の結果は理解できますが、これは2とインデックス型int(32ビットシステムでは4バイト)でインデックス付けされているため、8と配列のアドレスです。最後の行が8ではなく2である理由がわかりませんか?
さらに、最後の行のタイプは整数または整数ポインターですか?
この奇妙な動作をするのはC型システム(ちょっとしたキャスト)なのだろうか?
解決
a [2]
という表現の実際の意味を覚えておく必要があります。 *(a + 2)
とまったく同じです。そのため、同じ効果で 2 [a]
を記述することは完全に合法です。
それが機能し、意味をなすために、ポインター演算は、ポイントされたもののタイプを考慮します。しかし、それは舞台裏で処理されます。配列に自然なオフセットを使用するだけで、すべての詳細がうまくいきます。
同じロジックがポインターの違いに適用され、 2
の結果を説明します。
ボンネットの下の例では、インデックスに sizeof(int)
を掛けて、配列のベースアドレスに追加されるバイトオフセットを取得します。住所の2枚の印刷でその詳細を公開します。
他のヒント
同じタイプのポインターを減算すると、結果はバイト数ではなく要素数になります。これは設計によるものであるため、任意のタイプの配列に簡単にインデックスを付けることができます。バイト数が必要な場合は、アドレスをchar *にキャストします。
ポインターを1(p + 1)だけインクリメントすると、ポインターは(p + sizeof(Type))バイトをpに追加することにより、次の有効なアドレスを指します。 (Typeがintの場合、p + sizeof(int))
同様の論理はp-1にも有効です(もちろんこの場合は減算します)。
これらの原則をここに適用するだけの場合:
簡単に言えば:
a[2] can be represented as (a+2)
a[2]-a ==> (a+2) - (a) ==> 2
だから、舞台裏で、
a[2] - a[0]
==> {(a+ (2* sizeof(int)) ) - (a+0) } / sizeof(int)
==> 2 * sizeof(int) / sizeof(int) ==> 2
行& E [2] -2は、整数の減算ではなく、ポインターの減算を行っています。ポインター減算(両方のポインターが同じ型のデータを指す場合)は、アドレスの差を、それらが指す型のサイズで割った値を返します。戻り値はintです。
" update"に回答するには質問、もう一度ポインター演算(今回はポインターの追加)が実行されています。 Cでこのようにして、「インデックス付け」を簡単にします。ポインターが指す連続データのチャンク。
Pointer Arithmetic In C の質問と回答に興味があるかもしれません。
基本的に、+および-演算子は、ポインターで使用するときに要素サイズを考慮します。
Cでポインターを加算および減算するときは、絶対アドレスではなくデータ型のサイズを使用します。
intポインターがあり、それに数値2を追加すると、2 * sizeof(int)が進みます。同様に、2つのintポインターを減算すると、絶対アドレスの差ではなく、sizeof(int)の単位で結果が得られます。
(データ型のサイズを使用してポインターを保持することは非常に便利であるため、たとえば、毎回型のサイズを指定する代わりに p ++
を使用できます: p + = sizeof(int)
。)
整数/数値。同じトークンで:今日-4月1日=数。日付ではありません
バイトの違いを確認するには、次のようにサイズが1バイトの型にする必要があります。
printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0]))