このコードを考えると:
int *p, *q;
p = (int *) 1000;
q = (int *) 2000;
何がq - p
どのように?
標準によれば、実際には未定義です。ポインタが両方とも同じ配列内またはそのすぐ先の要素を指している場合を除いて、ポインタ演算が機能することは保証されません。
標準の関連セクションは6.5.6:9(c1xのn1362ドラフトですが、これはc99以降変更されていません)です。
2つのポインターを減算する場合、両方が同じ配列オブジェクトの要素を指すか、配列オブジェクトの最後の要素の1つ先を指します。結果は、2つの配列要素の添え字の違いです。
int
データ型が4バイトの場合、おそらく250を取得しますが、保証はありません。未定義の動作(実装定義の動作とは異なり)は、それだけを意味し、未定義です。時空の大部分の完全な破壊を含むまで、何でも起こり得ます。
復習コース:
q-pは250です。
2000 - 1000 = 1000
1000 / sizeof(int) = 250
sizeof(int)が4であると仮定して、ポインター演算。
struct foo { int ar[1000]; } big[10];
char small[10];
struct foo *fs, *fe;
char *ss, *se;
fs = &big[0]; fe = &big[9];
ss = &small[0]; se = &small[9];
fe - fs == se - ss;
つまり、この場合の2つのポインターの違いは、それらの間の配列要素の数です。この場合、0、1、...8または9要素です。
q-p
p
に移動するために実行する必要のあるステップ数を増分で返すことになっていますq
。これは1000 / sizeof(int)
250に等しいです。Rememberq++
は実際にはint型の次の要素に移動し、その途中ではないため、ポインタの実際の値に4を追加する必要があります。したがって、結果。
答えint
:anが4バイトのマシンを使用していると仮定すると、qpは250になります。
計算は次のとおりです。
q-p = 1000 1000/4(intのサイズ)= 250
その背後にある考え方:
ポインタ演算の背後にある考え方は、int
1000へのint
ポインタと2000へのポインタがあり、違いを尋ねる場合、 2000-1000は何であるかを尋ねないということです。あなたが求めているのは、2つの間にいくつint
のを収めることができるかということです。
これは、次のようなあらゆる種類の操作に非常に便利です。
int *i = 100;
i++; // This is **not** 101, it is 104, cause you actually want the next place an int could fit in memory.
これは、配列を扱うときに特に便利です。intの配列(定義済みint arr[10]
)は、基本的にポインターのように扱われます。を書くarr[5]
と、コンパイラはそれをに変換します。つまり、と呼ばれるポインタ*(arr + 5)
に5を追加し、そのアドレスの値を取得します。int
arr
これが機能する理由は、 「arrの値に5を追加する」という意味でarr + 5
はなく、「5秒進むためにarrの値に必要なものを追加する」int
、より正確には「5*sizeof(int)
を追加する」という意味であるためです。 arrの値」
pはintを指しているため、qは1000になります。