2016-12-04 6 views
2

現在のC標準によると、ポインタの違いはptrdiff_tです。同時に、標準によれば、配列の添え字は任意の整数型であり、最大の符号付き整数型は現在long longです。なぜptrdiff_tはlong longと同じではありませんか?

ptrdiff_tlong longではない場合、上記の2つのステートメントは矛盾しますか?

次に、標準でptrdiff_tタイプが導入され、ポインタの違いとしてlong longが使用されるのはなぜですか?

+3

'unsigned long long'が配列添字の有効な型であるという事実は、' unsigned long long'のすべての可能な値が配列添字の有効な値であるとは限りません。 (また、ポインタの違いに署名します。) – user2357112

+0

?あなたは最初の文を詳しく説明できますか?私はまったくそれを得ていない。私の無知を赦してくれそうです。そうですね、この二つの事柄は同じです。 –

+0

OKすでにそれについて議論している回答があります。 –

答えて

6

最初に、ptrdiff_tは符号付きの型です(2つのポインタの差は負になる可能性があります)ので、除外ルールはunsigned long longです。

配列の添字には任意の整数型を使用できますが、結果の値は境界内にある必要があります。たとえば、32ビットプラットフォームでは、約40億個以上の要素を持つ配列を持つことができないため、ptrdiff_tは32ビットの整数型になりそうです。 long long値が32ビットを超える配列を索引付けすると、未定義の動作(境界アクセスの発生)が発生します。

いつものように、実際の理由は下位互換性です。は、ptrdiff_tの後に長く言語に追加され、コンパイラが既に書かれた後にはptrdiff_tが追加されました。 (数十年の古い)振る舞いに依存している既存のコードがある場合、ポインタ算術に対して完全に異なるルールを指定することは意味がありません(「2つのポインタを減算して64+ビットの結果を得なければならない」など)。

+0

ありがとうございます。はい、私が理解しておくべき重要なことは、配列が宣言されたり正常に割り当てられたりすると、要素の数が十分に小さくなければならず、より小さい整数型「長い間」。 –

+1

"配列の添え字...結果の値は、' size_t'の範囲内の境界でなければなりません。 'ptrdiff_t'は、同じ配列内であっても、必ずしもすべてのポインタの相違に対して十分に広いわけではありません。 「結果がそのタイプのオブジェクトで表現できない場合、その動作は不確定です。」 C11§6.5.69しかし、ほとんどのアプリケーションでは 'ptrdiff_t'で十分です。 – chux

0

あなたは間違っています。 ptrdiff_tは、long long intの別名にすることができます。使用されるシステムとアドレスレジスタのサイズによって異なります。

したがって、配列はアドレスレジスタに格納できる値より大きくすることはできません。

未定義の動作につながる可能性のある別の問題があります。

問題は、2つのポインタの違いが負の数になる可能性があることです。したがって、符号なしの数値を結果として使用することはできません。また、指数もマイナスになる可能性があります。たとえば、次のコードスニペットを考えてみましょう

const char *s = "aabbcc"; 
size_t n = 0; 

for (const char *p = s; *p++;) 
{ 
    if (p[0] == p[-1]) ++n; 
} 

有効なコードです。

したがって、ポインタ演算には符号付きの数値が必要です。

一方、オブジェクトのサイズは、タイプsize_tによって確定されます。このサイズは、タイプunsigned long longと同じくらい大きくすることができます。

問題は、符号付き整数型の負でない値の範囲が、同じランクの符号なし型の負でない値の範囲を超えないことです。また、レジスタに格納される絶対アドレスは、負ではない数値です。

+0

はい私の質問は看板については正確ではなかった申し訳ありません...しかし、実際には、問題はそれに関するものではありませんでした。ありがとうございました。 –

0

ポインタは、マシンアーキテクチャに応じて、データレジスタのサイズよりも小さくても大きくてもかまいません。

また、物理メモリのサイズは、アドレス空間よりも大きい場合があります。

したがって、さまざまなアーキテクチャが可能であり、すべてがカバーされなければなりません。だから、ptrdiff_tがいくつかの具体的な符号付き整数型のエイリアスであっても、ポインタ関連の型はデータの整数型とは独立して定義されたままにしておくことが完全に合理的です。

私は常に可能な限りポータブルとしてコードを作成しようと努力していますが、できるだけ厳密に標準に準拠し、私のニーズに最も適した標準タイプを使用します。

関連する問題