0

この質問は、一般的には概念的な質問であり、本質的にコーディングの問題ではありません。これらのコードに出くわしたとき、私は好奇心旺盛で、それらが有効かどうか疑問に思いました。または、なぜ基本的に、誰かが私に説明をしてくれるなら?

Cでの型宣言は次のとおりです。

typedef struct Rec1 * Ptr1;
typedef struct Rec2 * Ptr2;

struct Rec1
{
    int data;
    Ptr2 next;
};

struct Rec2
{
    double data;
    Ptr2 next;
};

これらは許可されるべきですか?彼らは許可されていますか?なぜまたはなぜそうではないのですか?

4

4 に答える 4

3

それらは有効ですか?

はい、有効です

理由:

  1. 最初の2行は、aと。の型定義としてPtr1とを作成します。Ptr2struct Rec1 *struct Rec2 *

  2. それらはポインタであり、構造自体ではないため、struct Rec1およびstruct Rec2を不完全な型として作成Rec2し、再帰型(通常はデータ構造の作成に使用)およびオブジェクトRec1へのポインタを作成しているだけです。Rec2

それらは許可されるべきですか?

他にどのようにして自己参照構造を作成できますか?

于 2013-02-26T02:37:55.093 に答える
1

短いバージョン:

  • それは許可されるべきですか?はい

  • それらは(フォワードタイプタイプ定義)ですか?はい。

  • なぜまたはなぜそうではないのですか?

これは、フォワード型宣言を行うために一般的に受け入れられている方法です。これにより、不完全な型を宣言し、後で定義することができます。これは、このような単純なケースでは大したことではありませんが、より複雑なケースでは絶対に必要になる可能性があります。

LinuxまたはDarwinカーネルはどちらも、この手法をかなり広範囲に使用して、独自のヘッダーファイルでデータ型を定義できるように内部カーネル構造を宣言しますが、完全に定義される前にデータ型を使用できます。

このメカニズムがなければ、複雑で相互依存するデータ型の定義は不可能です。

于 2013-02-26T02:39:01.410 に答える
1

言語標準によれば、それらは有効であるため、許可する必要があります。

さて、これがどのように機能するかを尋ねると、それは非常に簡単です。

通常、ポインタは単なるメモリアドレスです。また、オブジェクトが整数バイト(それぞれが一意のアドレスを持っている)で表されている場合は、メモリ内の任意のオブジェクトへのポインタを持つことができます。ここでは、構造ビットフィールドへのポインタを設定できないため、「整数」と言っています(少なくとも、バイト境界で始まり、整数のバイト数を占めるものへのポインタを設定することはできません)。 。

つまり、これPtr2は事前にわかっているサイズのポインタタイプです(CPUのアドレス空間が0〜4 GBの場合、32ビットのアドレスですべてのバイトをアドレス指定できます。32ビットがこのCPUのネイティブポインタサイズになります)。でそのようなポインタstruct Rec1にスペースを割り当てることができ、struct Rec2このポインタが何を指しているのかがまだわかっていなくても、問題のコードにあります。不完全な型として定義されています。これが正式な名前ですPtr1Ptr2

このような不完全なポインタ型を言語で実装する理由は非常に実用的です。リンクリストまたはツリーを作成する場合、それらの要素またはノードは、リンクされている他の要素またはノードを何らかの方法で指す必要があります。理論的には、最後の要素(またはリーフノード)に対して、次にそれを指す要素に対して、次にその要素を指す要素に対して、というように、個別の要素/ノードタイプを作成できます。ただし、要素またはノードが数個以上ある場合、これは適切にスケーリングされません。あなたがそれらの百万が欲しい場合はどうなりますか?ほぼ同一のタイプを100万個定義することは、せいぜい実用的ではありません。したがって、この言語はこれを回避するためのショートカットを提供します。nextポインタを単なるポインタとして宣言することもできますvoid*が、その場合は、ポインタをどこにでもキャストする必要がありますstruct Rect1*struct Rect2*このようなコードの保守とデバッグはエラーが発生しやすくなります。だから、そこで、言語はあなたに手を差し伸べます。

于 2013-02-26T03:16:03.620 に答える
0

typedefは、それが参照する実際の型の単なるエイリアスです。マクロと考えることもできますが、コンパイルの前処理段階で置き換えられるものではありません。

Ptr1のすべてのオカレンスをstructRec1 *置き換えるだけで、有効なコードが生成されます。これは、コードが有効かどうかを確認する最も簡単な方法です;)

于 2013-02-26T02:39:22.037 に答える