3

私は、これらのコード行がCおよびC++で未定義の動作を生成する可能性があるかどうかを自問していました。私は、標準が配列の添え字について述べていることを読んで、各ポイントに答えようとしました(C 6.5.6-8)。段落がかなり長いので、段落全体を投稿しませんでした。

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

   1  int a[10];
   2  int b = a[9]; // ok
   3  int c = a[10]; // UB
   4  int* d = (a + 10); // ok
   5  int* e = &a[10]; // ok from C99 (& and [] are ignored, pointer is not deferenced), // UB in pre C99
   6  int* f = &a[11]; // ok from C99, UB in pre c99 
      int* g = a;
   7  int* h = g + 15; // ok

同じ答えがC++にも当てはまるはずだと思います

これらの行はCおよびC++で有効ですか、標準を誤解しましたか?

4

1 に答える 1

4

6も7も、既存の配列内でポインター演算を実行しないため(1つ過去のポインターを含む)、有効ではありません。他のすべては本質的に正しいです。

Cのみ:これa[i]はと同じ*(a + i)であり、&*p常にp評価なしであるとすると*p、5は常に問題ありませんが、C89はこれを指定せず、これはC99でのみ追加されました。&(これは、演算子がオーバーロードされる可能性があり、との組み合わせについての言及がないC ++ではまったく当てはまりません*。)

n1570(ドラフトからC11)から、6.5.6のパラグラフ8の加算演算子:

[...]ポインタオペランドと結果[のP + N]の両方が同じ配列オブジェクトの要素を指している場合、または配列オブジェクトの最後の要素を1つ過ぎている場合、評価はオーバーフローを生成してはなりません。それ以外の場合、動作は定義されていません。[...]

C ++には、非常によく似た表現が含まれています(C ++ 11、5.7 / 5など)。

于 2012-09-30T20:57:39.823 に答える