セクタ内のポインタの加算と減算。 6.5.6

私はC99欄6.5.6(加算演算子)の段落8と9を理解しようとしています。

パラ8の意味は次のとおりです。

int a [4];

int *p = a;
p --;      /* undefined behaviour */

p = a + 4; /* okay */
p --;      /* okay */
p += 2;    /* undefined behaviour */

p = a;
p += 5 - 5;    /* okay */
p = p + 5 - 5; /* undefined behaviour */

パラグラフ9について、私の理解は、ptrdiff_tは常に2つのポインタの違いを保持するのに十分な大きさであるということでした。しかし、文言: '値がptrdiff_t型のオブジェクトに適合していれば、この理解が間違っていると思われるようです。私の理解は間違っているのか、C99は何かを意味していた

You can find a link to the draft standards here: http://cboard.cprogramming.com/c-programming/84349-c-draft-standards.html

2
@BlagovestBuyukliev最初の p - のリンクは、残りの部分はどうですか?
追加された 著者 tyty,
@Bret:単に p + 5 p - 1 を計算するだけでUBが呼び出されます。 の6.5.6/8を参照してください。 C99スタンダード
追加された 著者 pmg,
追加された 著者 Blagovest Buyukliev,
段落へのリンクを追加したり引用したりできますか?私たちのいくつかは怠惰です。 :-)
追加された 著者 Codie CodeMonkey,

2 答え

私はあなたの解釈が正しいとは思わない。私が持っているバージョンでは(n1256)パラグラフ9の状態:

結果がその型のオブジェクトで表現できない場合、   動作は未定義です

それだ。差が PRTDIFF_MAX より大きいか PTRDIFF_MIN より小さい場合、その動作は未定義です。

これは、プログラマが ptrdiff_t に収まるかどうかをチェックする負担をかけることに注意してください。 「怠惰な」プラットフォームの実装では、 ptrdiff_t のために狭いタイプを選ぶだけで、それを扱うことができます。

それをチェックすることは、UBを誘発することなく差し引きを行うことができないため、直感的ではありません。あなたは、2つのポインタが同じオブジェクトの内側(またはそれを越えて)を指し、その周囲のオブジェクトの境界がどこにあるかという情報を使用しなければなりません。

2
追加された

私は第8項の理解に同意します。

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

Cは配列内にポインタオーバーフローがないと仮定しているので、配列の内部にいる間はポインタを増減できます。結果ポインタが配列を離れると、オーバーフローが発生し、動作が未定義になります。

パラグラフ9については、たとえば、32ビット・ポインタと32ビット・データ型を与えるアーキテクチャがあるかもしれないが、実際には2つの32ビット・ポインタの違いは符号+ 32ビット(33各ポインタの差が32ビットのptrdiff_tに一致するわけではありません。 2補完アーキテクチャではこれは問題ではありませんが、他のアーキテクチャでは問題になる可能性があります。

0
追加された
実際には、配列の中にポインタのオーバーフローがないこと、または配列の最後を越えて要素が1つだけ移動するという標準では、命令がありますが、この最後のケースではポインタを逆参照できません。
追加された 著者 JeremyP,
なぜあなたは2つの補数で問題はないと思いますか?可能な値のスペースは、大きすぎて32ビットの数量に収まりません。あなたは常にサインを追加で追跡する必要があります。
追加された 著者 Jens Gustedt,