CとC++のtypedefおよびstruct名前空間では、コメントの1つは、 struct foo
...の行に沿ってtypedefを使用するよりも、いくつかを公開する方が望ましいことを示唆しているようです。
typedef struct foo foo;
...そしてAPI全体のfoo
代わりに使用します。struct foo
後者のバリアントに欠点はありますか?
CとC++のtypedefおよびstruct名前空間では、コメントの1つは、 struct foo
...の行に沿ってtypedefを使用するよりも、いくつかを公開する方が望ましいことを示唆しているようです。
typedef struct foo foo;
...そしてAPI全体のfoo
代わりに使用します。struct foo
後者のバリアントに欠点はありますか?
唯一の欠点(*)は、構造体であるという事実を隠し、foo
一部の組み込み型のエイリアスではないことです。
注(*):これがあなたにとってマイナス面であるかどうかは好みの問題です。
それはあなたがその言葉をどれだけ好きかによりますstruct
。struct that
とを自由に振りかけることでプログラムがより明確になると思われる場合は(もちろん、C ++では使用struct tother
できません)、必ずそのバージョンを使用してください。struct this
struct
個人的には、繰り返すことで何のメリットもないと思いますので、名前struct
だけを使ってよかったです。typedef
また、C ++はtypedef struct xyz xyz;
宣言を効果的に自動的に提供するため(特にC ++で明示的に記述できるため、正確ではありませんが、十分に近いため、心配する必要はありません)、完璧になると思います。 Cでも同じように使用する意味があります。Cコンパイラはそれに満足しているので、私は通常、必要に応じtypedef struct tag tag;
て使用してから使用tag
しtag *
ます。
別の、しかし完全に維持可能なビューについては、Linuxカーネルコーディングスタイルガイドをお読みください。
typedef
C2011では、同じタイプのエイリアスである限り、を再定義できることに注意してください。
ISO / IEC 9899:2011§6.7宣言
セマンティクス
¶5宣言は、一連の識別子の解釈と属性を指定します。識別子の定義は、次のような識別子の宣言です。
—オブジェクトの場合、ストレージはそのオブジェクト用に予約されます。
—関数の場合、関数本体を含みます。119)
—列挙定数の場合、は識別子の(唯一の)宣言です。
— typedef名の場合、は識別子の最初の(または唯一の)宣言です。
これが不可能だったC99と比較してください。
セマンティクス
¶5宣言は、一連の識別子の解釈と属性を指定します。識別子の定義は、次のような識別子の宣言です。
—オブジェクトの場合、ストレージはそのオブジェクト用に予約されます。
—関数の場合、関数本体を含みます。98)
—列挙定数またはtypedef名の場合、は識別子の(唯一の)宣言です。
これにより、一貫性がある限り、型定義の作成が簡単になります(ただし、関連する各プラットフォームに十分な互換性のあるC2011コンパイラがある場合のみ)。
typedef構造体タイプにするかどうかについて:
ここにいくつかの意見があります(すべてtypedefing構造に対して):
OpenBSDスタイルガイドから:
「構造体型にtypedefを使用することは避けてください。これにより、アプリケーションがそのような構造体へのポインターを不透明に使用できなくなります。これは、通常の構造体タグを使用する場合に可能であり、有益です。」
Linuxカーネルコーディングスタイルから:
「構造体とポインターにtypedefを使用するのは間違いです。」
Peter VanderLindenによるExpertCProgrammingから:
「構造体のtypedefを気にしないでください。構造体は、「構造体」という単語を書く手間を省くだけです。これは、とにかく隠してはいけない手がかりです。」
それは多かれ少なかれ好みの問題です。
タグを宣言するだけstruct
で、同じスコープ内の変数、関数、または列挙子(または、混乱している場合は別のタイプ)に名前を使用することもできます。また、ユーザーは単語を記述する必要がありますstruct
。これにより、コードがより明確になります。
タイプ名も宣言することで、入力struct
したくない場合に入力しないようにすることができます。
他の質問での私のコメントは、structタグと同じ名前のポインター型の宣言に言及していました。
typedef struct foo * foo;
様式的には、これはポインタであるという事実を隠すため、少し不快です。これは、それがポインタであるという事実を隠します。これはAPIによって定義された不透明(OPAQUE)型であるという質問のコンテキストではおそらく問題ありませんが、私の意見では、非不透明(OPAQUE)型にはかなり失礼です。また、C++との互換性も失われます。その言語では、このような宣言は無効です。これは、個別のタグスペースではなく現在の名前空間にstruct foo
導入され、その名前空間で同じ名前を持つ他のタイプの宣言を防ぐためです。foo
命名規則に固執するだけで大丈夫です。
typedef struct
{
//...
} t_mytype;
//...
t_mytype thing;
このようにして、それがカスタムタイプであることがわかります。構造体である場合は、明示的な名前を使用するだけで、実際には使用しないでくださいt_mytype
typedefに対するもう1つの論拠は、クリーンなヘッダーを作成することの難しさです。ヘッダーの例を見てみましょう。
#ifndef HEADER_H
#define HEADER_H
#include "s.h"
void f(struct s *);
#endif
このヘッダーは改善できます。確かに、struct s
定義する必要はありません。したがって、次のように書くことができます。
#ifndef HEADER_H
#define HEADER_H
struct s;
void f(struct s *);
#endif
したがって、ユーザーはstruct s
不透明な構造体として使用でき、"s.h"
プライベートに保つことができます。
同じことをしましょうが、typedef
:
#ifndef HEADER_H
#define HEADER_H
typedef struct s s_t;
void f(s_t *);
#endif
この行typedef struct s s_t
は、使用したいすべてのヘッダーに表示され、s_t *
冗長なコードは嫌いです。これを回避する方法は複数ありますが、おそらく最も簡単なのはtypedefを取り除くことです。