13

このコードを考えると:

int *p, *q;

p = (int *) 1000;
q = (int *) 2000;

何がq - pどのように?

4

5 に答える 5

34

標準によれば、実際には未定義です。ポインタが両方とも同じ配列内またはそのすぐ先の要素を指している場合を除いて、ポインタ演算が機能することは保証されません。

標準の関連セクションは6.5.6:9(c1xのn1362ドラフトですが、これはc99以降変更されていません)です。

2つのポインターを減算する場合、両方が同じ配列オブジェクトの要素を指すか、配列オブジェクトの最後の要素の1つ先を指します。結果は、2つの配列要素の添え字の違いです。

intデータ型が4バイトの場合、おそらく250を取得しますが、保証はありません。未定義の動作(実装定義の動作とは異なり)は、それだけを意味し、未定義です。時空の大部分の完全な破壊を含むまで、何でも起こり得ます。

復習コース:

  • 定義された動作は、標準で義務付けられているものです。実装は、準拠するためにこれを行う必要があります。
  • 実装で定義された動作は実装に任されていますが、その動作を明確に文書化する必要があります。移植性をあまり気にしない場合は、これを使用してください。
  • 未定義の動作は、何かが起こる可能性があることを意味します。絶対にしないでください!
于 2010-01-22T13:37:51.613 に答える
8

q-pは250です。

2000 - 1000 = 1000
1000 / sizeof(int) = 250

sizeof(int)が4であると仮定して、ポインター演算。


編集:わかりました、明確にするために。Cでは、2つのポインターが同じタイプである場合、それらの違いは、それらの間のポイントされたタイプのものの数として定義されます。例えば、

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要素です。

于 2010-01-22T13:37:50.697 に答える
2

q-ppに移動するために実行する必要のあるステップ数を増分で返すことになっていますq。これは1000 / sizeof(int)250に等しいです。Rememberq++は実際にはint型の次の要素に移動し、その途中ではないため、ポインタの実際の値に4を追加する必要があります。したがって、結果。

于 2010-01-22T13:40:43.447 に答える
2

答えint:anが4バイトのマシンを使用していると仮定すると、qpは250になります。

計算は次のとおりです。

q-p = 1000 1000/4(intのサイズ)= 250

その背後にある考え方

ポインタ演算の背後にある考え方は、int1000への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を追加し、そのアドレスの値を取得します。intarr

これが機能する理由は、 「arrの値に5を追加する」という意味でarr + 5なく、「5秒進むためにarrの値に必要なものを追加する」int、より正確には「5*sizeof(int)を追加する」という意味であるためです。 arrの値」

于 2010-01-22T13:45:20.120 に答える
-7

pはintを指しているため、qは1000になります。

于 2010-01-22T13:37:34.997 に答える