1

これは、私が何を意味するかを説明するための簡単なプログラムです。長さ n を指定すると、標準入力によって読み取られる n 個の整数のシーケンスを初期化します。

int n, *seq, *current;
scanf("%d", &n);
seq = malloc(n*sizeof(int));
for (current = seq; current - seq < n; current++)
  scanf("%d", current);

私の疑問は、最後のインクリメントがcurrent割り当てられたメモリの外側の何かを指すようにすることです。明らかに、その場所から読み取るのはエラーです。しかし、その場所を読んでいない場合はどうなりますか?

プログラムは正しく実行されますが、私の質問は次のとおりです。

更新:そして、これを前のプログラムの最後に追加するのはどうですか?

for (current--; current - seq >= 0; current--)
  printf("%d\n", *current);

@MOHAMEDの回答によると、それは無効な場所へのアクセスであるからではなく、最初の要素の1つ前の場所を指してcurrent - seq >= 0いる場合に間違った結果が得られる可能性があるため、間違っています。current

4

3 に答える 3

6

このトピックから:

はい、ポインターは、配列の末尾を少し過ぎた位置を指すことができます。ただし、そのようなポインタを参照することは許可されていません。

C99 6.5.6/8 加法演算子 (強調を追加)

式 P が配列オブジェクトの最後の要素を指している場合、式 (P)+1 は配列オブジェクトの最後の要素の 1 つ後ろを指し、式 Q が配列オブジェクトの最後の要素の 1 つ後ろを指している場合、式(Q)-1 は、配列オブジェクトの最後の要素を指します。ポインター オペランドと結果の両方が同じ配列 object の要素を指している場合、または配列 object の最後の要素の 1 つ後ろを指している場合、評価はオーバーフローを生成しません。それ以外の場合、動作は未定義です。結果が配列オブジェクトの最後の要素の 1 つ後ろを指している場合、評価される単項 * 演算子のオペランドとして使用されません。

UPDATEについて

そして、このトピックによると:

あなたの場合、比較current - seq >= 0未定義の動作です。が と等しい場合、反復後current - seqに がデクリメントされると未定義になります。currentseq

これは、標準のパート 8 のセクション 6.5.6 でカバーされています。

整数型の式をポインターに加算またはポインターから減算すると、結果はポインター オペランドの型になります。ポインターオペランドが配列オブジェクトの要素を指し、配列が十分に大きい場合、結果は元の要素からオフセットされた要素を指し、結果と元の配列要素の添字の差が整数式と等しくなります。つまり、式Pが配列オブジェクトの i 番目の要素を指している場合、式(P)+N(同等にN+(P)) と(P)-N( where Nhas the value ) は、配列オブジェクトの- 番目と- 番目の要素をnそれぞれ指しています。それらは存在します。さらに、式の場合i+ni−nP配列オブジェクトの最後の要素を指す場合、式は配列オブジェクトの最後の要素の 1 つ後ろを指し、式が配列オブジェクトの最後の要素の 1 つ後ろを指す(P)+1場合、式は配列オブジェクトの最後の要素を指します。ポインターオペランドと結果の両方が同じ配列オブジェクトの要素を指している場合、または配列オブジェクトの最後の要素の 1 つ後ろを指している場合、評価はオーバーフローを生成しません。それ以外の場合、動作は undefinedです。結果が配列オブジェクトの最後の要素の 1 つ後ろを指している場合、評価される単項演算子のオペランドとして使用されません。Q(Q)-1*

標準では、配列オブジェクトの最後の要素の 1 つ後ろの位置にある要素をカバーする長さになりますが、最初の要素の 1 つ前の位置にある要素は、上記の規則の「そうでない」節に該当します。

于 2013-11-01T08:43:07.840 に答える
2

ポインターを再度使用しない場合 (再割り当てしない限り) は問題ありません。

ポインターを持っているだけでは、未定義の動作は発生しません。問題を引き起こす可能性があるのは、いつ、どのように使用するかです。だから使わないと何も始まらない。

于 2013-11-01T08:40:54.673 に答える
0

それは問題ありませんが、以下はおそらくより明確でエラーが発生しにくいものです:

int n, *seq, counter;
scanf("%d", &n);
seq = malloc(n*sizeof(int));
for (counter = 0; counter < n; counter++)
  scanf("%d", &seq[counter]);
于 2013-11-01T08:44:30.987 に答える