質問

最近の C および C++ コードでは次のように使用されているようです。 size_t の代わりに int/unsigned int C 文字列関数のパラメーターから STL に至るまで、ほとんどどこにでもあります。その理由とそれがもたらすメリットに興味があります。

役に立ちましたか?

解決

size_t type は、次の結果である符号なし整数型です。 sizeof 演算子 (および offsetof 演算子))、そのため、システムが処理できる最大のオブジェクトのサイズ (例: 8Gb の静的配列) を含めるのに十分な大きさであることが保証されます。

size_t 型は、 unsigned int, と、コンパイラが最適化のためにそれについて仮定する場合があります。

より正確な情報は、C99 標準のセクション 7.17 で見つけることができます。草案はインターネットで入手できます。 pdf 形式、または C11 標準セクション 7.19 の形式としても利用可能です。 PDF ドラフト.

他のヒント

Classic C (ブライアン・カーニハンとデニス・リッチーが『C プログラミング言語』、プレンティス・ホール、1978 年に記述した C の初期の方言) では、次のような機能は提供されませんでした。 size_t. 。C 標準委員会が導入 size_t 携帯性の問題を解決するために

embedded.com で詳しく説明されています (非常に良い例を示しています)

要するに、 size_t が負になることはなく、ターゲット プラットフォーム上で可能な最大のオブジェクトのサイズを表すのに十分な大きさであるが、大きすぎない符号なし整数型になるように typedef されているため、パフォーマンスが最大化されます。

サイズは決して負であってはなりません。 size_t 符号なし型です。また、なぜなら、 size_t が符号なしの場合、符号なし整数の他のすべてのビットと同様に、符号ビットを使用して大きさを表すことができるため、対応する符号付き型の約 2 倍の大きさの数値を格納できます。さらに 1 ビットを獲得すると、表現できる数値の範囲が約 2 倍になります。

では、なぜ単に unsigned int?十分な数を保持できない可能性があります。実装では、 unsigned int は 32 ビットです。表現できる最大の数値は次のとおりです。 4294967295. 。IP16L32 などの一部のプロセッサは、次のサイズより大きいオブジェクトをコピーできます。 4294967295 バイト。

では、なぜ使用しないのかというと、 unsigned long int?一部のプラットフォームではパフォーマンスに大きな負担がかかります。標準 C では、 long 少なくとも 32 ビットを占有します。IP16L32 プラットフォームは、各 32 ビット長を 16 ビット ワードのペアとして実装します。これらのプラットフォーム上のほぼすべての 32 ビット演算子は、2 つの 16 ビット チャンクで 32 ビットを処理するため、それ以上ではないにしても 2 つの命令を必要とします。たとえば、32 ビット長を移動するには、通常 2 つのマシン命令が必要です (16 ビットのチャンクごとに 1 つ)。

使用する size_t このパフォーマンスへの負担を回避します。によると この素晴らしい記事, 、 "タイプ size_t typedef は、符号なし整数型のエイリアスです。通常、 unsigned int または unsigned long, 、しかしおそらく unsigned long long. 。標準 C の各実装では、ターゲット プラットフォーム上で可能な最大のオブジェクトのサイズを表すのに十分な大きさの、ただし必要以上に大きくない符号なし整数を選択する必要があります。」

size_t 型は、sizeof 演算子によって返される型です。これは、ホスト マシンでサポートされているメモリ範囲のサイズをバイト単位で表現できる符号なし整数です。これは、ptrdiff_t が sizeof(ptrdiff_t) と sizeof(size_t) が等しいような符号付き整数値であるという点で (通常は) ptrdiff_t に関連しています。

C コードを記述するときは、次のことを行う必要があります。 いつも メモリ範囲を扱うときは常に size_t を使用してください。

一方、int 型は基本的に、ホスト マシンが整数演算を最も効率的に実行するために使用できる (符号付き) 整数値のサイズとして定義されます。たとえば、多くの古い PC タイプのコンピュータでは、sizeof(size_t) の値は 4 (バイト) ですが、sizeof(int) は 2 (バイト) になります。16 ビット演算は 32 ビット演算より高速でしたが、CPU は最大 4 GiB の (論理) メモリ空間を処理できました。

int 型は、実際の精度がコンパイラ オプションとマシン アーキテクチャの両方に大きく依存するため、効率を重視する場合にのみ使用してください。特に、C 標準では次の不変条件が指定されています。sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) これらの各プリミティブ型についてプログラマが利用できる実際の精度の表現には他の制限はありません。

注記:これは、Java の場合 (実際には、「char」、「byte」、「short」、「int」、「long」の各型のビット精度を指定します) とは異なります。

size_t 型は、あらゆるオブジェクトのサイズを格納できる十分な大きさでなければなりません。Unsigned int はその条件を満たす必要はありません。

たとえば、64 ビット システムでは、int および unsigned int は 32 ビット幅になる可能性がありますが、size_t は 4G より大きな数値を格納できる十分な大きさでなければなりません。

glibc マニュアル 0.02 からのこの抜粋も、このトピックを調査するときに関連する可能性があります。

size_t タイプとリリース 2.4 より前のバージョンの GCC には潜在的な問題があります。ANSI C では、size_t が常に符号なし型であることが要求されます。既存のシステムのヘッダー ファイルとの互換性のために、GCC は size_t を次のように定義します。 stddef.h' to be whatever type the system'ssys/types.h' はそれを定義しています。`sys/types.h' で size_t を定義するほとんどの Unix システムは、それを符号付き型として定義します。ライブラリ内の一部のコードは、size_t が符号なし型であることに依存しており、符号付きの場合は正しく動作しません。

size_t が符号なしであることを期待する GNU C ライブラリ コードは正しいです。size_t の符号付き型としての定義が正しくありません。バージョン 2.4 では、GCC は常に size_t を符号なし型として定義する予定です。 fixincludes' script will massage the system'ssys/types.h' これと競合しないようにします。

それまでの間、GNU C ライブラリをコンパイルするときに size_t に unsigned 型を使用するように GCC に明示的に指示することで、この問題を回避します。`configure' は、GCC が size_t に使用するタイプを自動的に検出し、必要に応じてオーバーライドします。

コンパイラが 32 ビットに設定されている場合、 size_t は、次の typedef に他なりません。 unsigned int. 。コンパイラが 64 ビットに設定されている場合、 size_t は、次の typedef に他なりません。 unsigned long long.

size_t はポインタのサイズです。

したがって、32 ビットまたは一般的な ILP32 (整数、長整数、ポインター) モデルでは、size_t は 32 ビットになります。64 ビットまたは一般的な LP64 (ロング、ポインター) モデルでは、size_t は 64 ビットです (整数は 32 ビットのままです)。

他のモデルもありますが、これらは g++ で使用されるものです (少なくともデフォルトでは)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top