web-dev-qa-db-ja.com

構造体へのポインターのC typedef

私は次のコードに出くわしました:

typedef struct {
        double x;
        double y;
        double z;
} *vector;

これは有効な型定義ですか?コードは正常にコンパイルおよび実行されます。これが一般的な慣行であるかどうかだけに興味がありました。

35
user187174

絶対に有効です。通常、2つのタイプを一緒に定義することにより、この方法を最大限に活用できます。

typedef struct
{
 int a;
 int b;
} S1, *S1PTR;

ここで、S1は構造体で、S1PTRはこの構造体へのポインタです。

55
alexkr

はい、そうです。しかし、それは私見悪いスタイルです。構造体の直接宣言ではなく、ポインター型の直接宣言。難読化です。特定の変数またはパラメーターがポインター(および配列の場合はそれよりも少ない範囲)であるという情報は、コードを読み取るときに非常に重要です。

コードをレビューするとき、どの関数が副作用を持っているかどうかを一見しただけではわかりにくいことがよくあります。使用されるタイプがこの情報を隠す場合、読者に記憶の負担がかかります。

int do_fancy(vector a, vector b); 

または

int do_fancy(vector *a, vector *b);

最初のケースでは、その関数がaまたはbの内容を変更する可能性があることを簡単に見逃してしまいます。第二に、私は警告されます。

また、実際にコードを書くとき、a->xそしてコンパイラーに教えてくれないerror: request for memberx 'は、構造体でも共用体でもありません。

個人的な趣味のように見えますが、多くの外部コードを操作したことから、変数の間接レベルを認識しないと、非常に迷惑になることを保証できます。それが、C++参照(Javaでは、すべてのオブジェクトが参照で渡されるためではなく、一貫性がある)とMicrosoftのLPCSTR種類の型も嫌いです。

25

はい、有効です。より多くの「セキュリティ」が必要な場合は、次のこともできます

typedef struct vector_{
        double x;
        double y;
        double z;
} *vector;

その後、両方を使用できます

struct vector_ *var;
vector var;

しかし、最後のセミコロンを忘れないでください。

Typedefのみを使用すると、そのように名前を付けることを意味します。それ以外の場合は、多かれ少なかれ匿名になります。

3
Tobias Wärre

それは有効なものであり、新しいタイプを定義します。 @Alexが言ったように、型とポインター型を定義すると便利です。

使用するだけでより多くのポインタを作成できます

S1PTR ptr1, ptr2, ptr3, ...;  

の代わりに

S1 *ptr1, *ptr2, *ptr3, ...;
2
Siva

はい、上記の回答で説明されているように有効です。ちょっとした提案ですが、次のようにタグ名も指定した方が良いでしょう。これは、一部のIDEがコードをより適切に解析するのに役立ちます。

typedef struct vactor_tag {
        double x;
        double y;
        double z;
} *vector;
1
FIFO