53

stdintプラットフォーム間の移植性のために特定の変数サイズが必要な場合に使用されることは既に知っています。今のところそのような問題はありませんが、上記の事実以外に、それを使用することの長所と短所は何ですか?

これをstackoverflowおよび他のサイトで探していると、テーマについて扱う2つのリンクが見つかりました。

この 2 つのリンクは、このヘッダーの主な理由である移植性について詳しく知りたい場合に特に役立ちます。しかし、私にとって最も気に入っているのは、 (たとえば、RBG チャネル値を格納するための)uint8_tよりもクリーンであると思うこと、単純に より意味のあるように見えることなどです。unsigned charint32_tint

stdintそれで、私の質問は、移植性以外に使用することの長所と短所は正確には何ですか? コードの特定の部分でのみ使用する必要がありますか、それともどこでも使用する必要がありますか? どこにでもある場合atoi()strtok()、 などの関数を使用するにはどうすればよいですか?

ありがとう!

4

4 に答える 4

80

長所

int適切に定義された型を使用すると、コードの移植がはるかに簡単かつ安全になります。たとえば、あるマシンが 16 ビットとして解釈され、別のマシンが 32 ビットとして解釈されたとしても驚くことはありません。stdint.h では、入力した内容が取得されます。

etcを使用intすると、危険なタイプのプロモーションを検出することも難しくなります。

もう 1 つの利点は、int8_tの代わりに を使用することでchar、常に符号付き 8 ビット変数を取得できることです。charこれは実装定義の動作であり、コンパイラによって異なります。したがって、char移植可能である必要があるコードでデフォルトを使用するのは明らかに危険です。

変数を最適化する必要があるというコンパイラのヒントを与えたい場合はuint_fastx_t、少なくとも 'x' と同じ大きさの、可能な限り高速な整数型を使用するようコンパイラに指示する を使用できます。ほとんどの場合、これは問題ではありません。コンパイラは、入力した内容に関係なく、型のサイズを最適化するのに十分なほどスマートです。シーケンス ポイント間で、コンパイラは指定されたものとは異なる型に暗黙的に変更できます。結果には影響しません。

短所

なし。


参照: MISRA-C:2004 ルール 6.3.「基本型の代わりにサイズと符号を示すtypedefを使用する」

編集:間違った例を削除しました。

于 2012-03-23T10:13:49.953 に答える
19

uint8_t(見た目の好みは別として)を使用する唯一の理由は、プログラムが正確に 8 ビットであるunsigned char必要があることを文書化したい場合です。C 標準の要件に従って、 の場合にのみ存在します。charuint8_tCHAR_BIT==8

intX_tおよびタイプの残りの部分はuintX_t、次の状況で役立ちます。

  • ディスク/ネットワークの読み取り/書き込み (ただし、エンディアン変換関数も使用する必要があります)
  • 正確なカットオフで符号なしのラップアラウンド動作が必要な場合 (ただし、これは&オペレーターを使用するとより移植性が高くなります)。
  • パディングが存在しないことを確認する必要があるため、構造体の正確なレイアウトを制御している場合 (たとえば、memcmpまたはハッシュの目的)。

一方、uint_least8_tなどの型は、無駄に大きな型や遅い型を使用したくないが、特定の大きさの値を格納できることを保証する必要がある場合に役立ちます。たとえば、long longは少なくとも 64 ビットですが、一部のマシンでは 128 ビットである可能性があり、64 ビットの数値を格納できる型だけが必要な場合に使用すると、そのようなマシンでは非常に無駄になります。int_least64_t問題を解決します。

特定のマシンで型が変更されることがあり (ABI が壊れる)、通常は定義が間違っているため、[u]int_fastX_t型を完全に使用することは避けます。たとえば、x86_64 では、64 ビット整数型は 16、32、および 64 ビット値の「高速」と見なされますが、加算、減算、および乗算は、32 ビットを使用するかどうかにかかわらずまったく同じ速度です。ビット値または 64 ビット値の場合、除算は必要以上の型ではほぼ確実に遅くなり、それらが同じ速度であっても、2 倍のメモリを使用して何のメリットもありません。

最後に、ネイティブの整数サイズではない場合にカウンターを使用することの非効率性についていくつかの回答が行った議論は、int32_t技術的にはほとんど正しいですが、コードを修正することとは無関係であることに注意してください。最大カウントが制御下にあるいくつかの少数のもの、またはカウントが天文学的である可能性のある外部 (プログラムのメモリ内ではない) のものをカウントしていない限り、カウントの正しい型はほとんどの場合size_tです。これが、すべての標準 C 関数size_tがカウントに使用する理由です。よほどの理由がない限り、他のものを使用することは考えないでください。

于 2012-03-23T12:13:22.980 に答える
8

短所

intC 言語がまたはなどのサイズを指定しない主な理由longは、計算効率のためです。各アーキテクチャには自然で最も効率的なサイズがあり、設計者は、コンパイラの実装者が速度とコード サイズの効率のために自然なネイティブ データ サイズのデータ​​を使用することを特に権限を与え、意図しました。

過去数年間、他のマシンとの通信は主要な関心事ではありませんでした。ほとんどのプログラムはマシンに対してローカルでした。そのため、各データ型のサイズの予測可能性はほとんど問題ではありませんでした。

特定のアーキテクチャが特定のサイズを使用してカウントすることを主張することは、他のことをより簡単にするように見えてもint、本当に悪い考えです.

ある意味では、XML とその兄弟のおかげで、データ型のサイズはもはやあまり重要ではなくなりました。マシン固有のバイナリ構造をマシンからマシンへ転送することは、ルールではなく例外です。

于 2012-03-23T06:24:31.470 に答える
6

stdint 型を使用する理由は 1 つだけです。メモリに保持しているデータがディスク/ネットワーク/記述子にバイナリ形式で格納される場合です。リトルエンディアン/ビッグエンディアンの問題と戦うだけで済みますが、それは比較的簡単に克服できます。

stdint を使用しない明らかな理由は、コードがサイズに依存しない場合です。数学的に言えば、有理整数に対して機能するすべてのものです。たとえば、の展開ごとにのuint*_tバージョンを提供すると、醜いコードの重複が生成されます。qsort()*

その場合、怠惰なときに派生した独自の型、size_tまたはそうでないときにプラットフォームでサポートされている最大の符号なし整数を使用します。

以前にこの問題に遭遇したため、編集してください。
少なくともuint8_t、Solaris 2.5.1 で壊れているuint32_tことは注目に値すると思います。uint64_tそのため、移植性を最大限に高めるstdint.hために、(少なくとも今後数年間は) 回避することをお勧めします。

于 2012-03-23T10:44:12.230 に答える