内部で typedef を使用するかどうかを検討して<cstdint>
います。
私は個人的に何度も何度も書くことuint32_t
をunsigned int
好みます...私にとってははるかに直感的だからです。int8_t
char
皆さんはどう思いますか?typedef を使用することは良い考え <cstdint>
ですか? デメリットはありますか?
実際には、両方を使用することをお勧めします。
確実に 32 ビットの符号なしが必要な場合は、uint32_t を使用します。たとえば、仕様でフィールドの 1 つが 32 ビット符号なしとして定義されている外部オブジェクトを表す「構造体」を実装している場合。
「マシンの自然なワード サイズ」が必要な場合は、int または unsigned int を使用します。例えば:
for (int i = 0 ; i < 200 ; ++i)
// stuff
「マシンの自然なワード サイズ」は、現在のプロセッサでも将来のプロセッサでも最高のパフォーマンスを発揮します。
「文字」を意味する場合は「char」を使用します。「バイト」を意味する場合は「char」または「unsigned char」。C/C++ では、厳密に言えば、「char *」を介して任意のオブジェクトのバイトにアクセスできます。
特に 8 ビット整数が必要な場合は、uint32_t と同様に、uint8_t または int8_t を使用します。
両方を使用する必要があります。int
「適切なサイズの」整数が必要な場合は、他の回答で説明されているように、を使用する必要があります。文字が必要な場合に使用char
します。自己文書化です。
uint32_t
バイナリで外界とやり取りするときは、友だちを使用する必要があります。ネットワークプログラミングを行うとき、バイナリファイルを処理するとき、または外部のマルチバイトエンコーディングを使用するときなどです。これらの場合、タイプの正確なサイズは、正しく、ポータブルで、自己文書化コード。それが<stdint.h>
(またはC ++ 0x <cstdint>
)の目的です。
(エンディアンも同様に重要ですが、それはまったく別の問題です。)
変数の目的によって異なります。
ループ カウンターが必要な場合は、 を使用しますint
。文字列が必要な場合は、の配列を使用しますchar
。
-1 から 100 を保持できる数値変数が必要な場合は、これint8_t
で十分です。0 から 100,000 までの値を表す必要がある場合(@Serge に感謝) は優れた選択です。uint32_t
uint_least32_t
cstdintのtypedefを使用する必要がある特定の状況の1つは、多くのポインターからintへの変換を行うコードを処理する場合です。この場合、intptr_tを使用することが絶対的な要件です。
私が働いている会社では、32ビットから64ビットトンの低品質のC / C ++コードに移行する準備をしています。このコードは、ポインターをintにキャストしてから、ポインターに戻します。これは、64ビットアーキテクチャでは間違いなく失敗します。可能な限りコードをサニタイズし(つまり、データ構造とインターフェイスを変更してキャストの必要性を完全に排除し)、他の場所ではintの代わりにintptr_tを使用します。
ちなみに、キャストは一般的に疑わしいものですが、真剣に、整数へのポインターのキャストは、ほとんどの場合、設計のどこかにある重大な欠陥の結果です。基本的に、intの後ろにポインターを隠すたびに、コンパイラー、プラットフォーム、そしてさらに重要なことに同僚に嘘をついています。
それ以外は、他の人が言ったように、可能な場合はジェネリック型を使用し、必要な場合は明示的なサイズの型を使用します。
基本的に、uint32_t と unsigned int の間に手がかりがないようです。型が後でどのように使用されるかは必ずしもわからないため、これは完全に正常です。
typedef を使用するだけです。
unsigned int が必要か uint32_t が必要か (後で、プログラムがどうなるかをより完全に把握したときに考えることができます) が必要であるかどうかに関係なく、typedef を使用すると、実際の内容を指定してコードをより明確にすることができます。操作することで、最初の選択が最悪だった数か月後に別のタイプに変更しやすくなります。通常、これらのことを難しい方法で理解するため、ここに「正しい答え」はありません。uint32_t を必要とするライブラリと int を必要とする他のライブラリとの間の相互運用は苦痛です。
template
可能な限り s およびジェネリック プログラミングを使用します。必要がない場合は、どのタイプにも依存しないでください。
数値を受け取って 2 倍して返す関数がある場合は、次のように記述します。
template <typename Number>
inline Number doubleNum(Number n) {
return 2*n;
}
またはこれでも:
template <typename RetType, typename NumberType>
inline RetType doubleNum(NumberType n) {
return 2*n;
}
このようにして、s int
、double
s、sを使用するライブラリがある場合、uint64_t
名前を付けますが、コードを書き直すことなく、それを操作できます。バイナリ ファイルまたはネットワーク プログラミングを使用する必要がある場合は、コードを書き直すことなく、固定サイズの型を使用できます。また、任意精度の数値が必要な場合は、コードを書き直すことなく、GMP ラッパーなどの演算子のオーバーロードを介して、プリミティブ整数型または浮動小数点型と同じインターフェイスを実装するクラスを使用できます。
struct
また、テンプレート化された関数またはクラスを特殊化して、特定のケースを最適化したり、関連するインターフェイスに準拠していないクラス (または C ) を処理したりできます。
/*
* optimization:
* primitive integers can be bit-shifted left to
* achieve multiplication by powers of 2
* (note that any decent compiler will do this
* for you, behind the hood.)
*/
template <>
inline int doubleNum<int>(int n) {
return n<<1;
}
/*
* optimization:
* use assembly code
*/
template <>
inline int32_t doubleNum<int32_t>(int32_t n) {
asm {
...
}
}
/*
* work with awkward number class
*/
template <>
inline AwkwardNumber doubleNum<AwkwardNumber>(AwkwardNumber n) {
n.multiplyBy(2);
return n;
}