C99の配列インデックスにはどのタイプを使用する必要がありますか? LP32、ILP32、ILP64、LP64、LLP64などで動作する必要があります。 C89タイプである必要はありません。
5つの候補者を見つけました。
size_t
ptrdiff_t
intptr_t
/uintptr_t
int_fast*_t
/uint_fast*_t
int_least*_t
/uint_least*_t
問題をよりよく説明するための単純なコードがあります。これらの2つの特定のループにおけるi
とj
の最適なタイプは何ですか。正当な理由がある場合は、2つの異なるタイプでも問題ありません。
for (i=0; i<imax; i++) {
do_something(a[i]);
}
/* jmin can be less than 0 */
for (j=jmin; j<jmax; j++) {
do_something(a[j]);
}
追伸質問の最初のバージョンでは、負のインデックスについて忘れていました。
P.P.S. C99コンパイラを書くつもりはありません。しかし、コンパイラープログラマーからの回答は私にとって非常に価値があります。
同様の質問:
次の理由で_ptrdiff_t
_を使用する必要があると思います
size_t
_を含むすべての符号なし型は不適切です。p2 - p1
_の型は_ptrdiff_t
_です。 _i == p2 - p1
_の場合、_p2
_によって_p2 == p1 + i
_を取り戻すことができるはずです。 *(p + i)
は_p[i]
_と同等であることに注意してください。operator[]
_(ポインタなど)がユーザー提供の_operator[]
_(forベクトルの例)はまさにそれです( http://eel.is/c++draft/over.built#16 ):> すべてのcv修飾またはcv非修飾オブジェクトタイプTには、次の形式の候補演算子関数が存在します。
_T* operator+(T*, std::ptrdiff_t); T& operator[](T*, std::ptrdiff_t); T* operator-(T*, std::ptrdiff_t); T* operator+(std::ptrdiff_t, T*); T& operator[](std::ptrdiff_t, T*);
_
編集:本当に大きな配列または本当に大きなメモリ部分へのポインタがある場合、私の「一般的なインデックスタイプ」はそれをカットしません、その場合、最後の要素のアドレスから最初の要素のアドレスを減算できることが保証されないためです。 @Ciroの回答を使用する必要があります https://stackoverflow.com/a/31090426/34509 。個人的には、負のEdgeケース(たとえば、逆方向に反復するときのループの終了値)を表すことができないため、符号なしの型を使用しないようにしていますが、これは一種の宗教的な議論です(私はそのキャンプで一人ではありません) 。符号なしのタイプを使用する必要がある場合は、もちろん、私の宗教を脇に置く必要があります。