次のような C コードを見ました。
// A:
typedef uint32_t in_addr_t;
struct in_addr { in_addr_t s_addr; };
そして、私はいつもこのように好む:
// B:
typedef uint32_t in_addr;
だから私の質問は: B から A でそれを行うことの違い/利点は何ですか?
型安全性を導入するためのレイヤーであり、「将来の拡張」に役立つ可能性があります。
前者の問題の 1 つは、typedefed 組み込み関数によって表される型の値を、他のいくつかの型または typedefed 組み込み関数のいずれかに簡単に「変換」できることです。
検討:
typedef int t_millisecond;
typedef int t_second;
typedef int t_degrees;
対:
// field notation could vary greatly here:
struct t_millisecond { int ms; };
struct t_second { int s; };
struct t_degrees { int f; };
場合によっては、表記法を使用することが少し明確になり、コンパイラーは誤った変換も禁止します。検討:
int a = millsecond * second - degree;
これは疑わしいプログラムです。typedefed int を使用すると、それは有効なプログラムです。構造体を使用すると、形式が正しくありません。コンパイラ エラーには修正が必要であり、意図を明確にすることができます。
typedef を使用すると、任意の算術演算と変換が適用される可能性があり、それらが警告なしに相互に割り当てられる可能性があるため、維持するのが負担になる可能性があります。
以下も考慮してください。
t_second s = millisecond;
それは致命的な変換でもあります。
これは、ツールボックスの別のツールにすぎません。ご自身の判断で使用してください。
ジャスティンの答えは本質的に正しいですが、いくつかの拡張が必要だと思います:
編集: ジャスティンは彼の答えを大幅に拡張したため、これはやや冗長になります。
型の安全性 - データを整数として扱うだけでなく、データを操作する API 関数をユーザーに提供する必要があります。構造体でフィールドを非表示にすると、フィールドを間違った方法で使用することが難しくなり、ユーザーが適切な API に移動するようになります。
将来の拡張のために - おそらく将来の実装は物事を変えたいと思うでしょう。フィールドを追加するか、既存のフィールドを 4 文字に分割します。構造体を使用すると、API を変更せずにこれを行うことができます。
あなたの利益は何ですか?実装が変更されてもコードが壊れないこと。