質問
ポインターに関するCの前方参照とは何ですか?
例を入手できますか?
解決
前方参照。ポインターと他のPoDタイプでは前方参照がどのように異なるかわかりません。
型を前方宣言し、その型へのポインタである変数を宣言できることに注意してください:
struct MyStruct;
struct MyStruct *ptr;
struct MyStruct var; // ILLEGAL
ptr->member; // ILLEGAL
struct MyStruct {
// ...
};
// Or:
typedef struct MyStruct MyStruct;
MyStruct *ptr;
MyStruct var; // ILLEGAL
ptr->member; // ILLEGAL
struct MyStruct {
// ...
};
これは、ポインターと前方宣言を扱うときにあなたが求めているものだと思います。
他のヒント
「前方参照」と思うポインタに関しては、次のようなものを意味します。
struct MyStruct *ptr; // this is a forward reference.
struct MyStruct
{
struct MyStruct *next; // another forward reference - this is much more useful
// some data members
};
ポインターは、ポインターが指す構造が定義される前に宣言されます。
ポインターはアドレスを格納するため、コンパイラーはこれを回避できます。ポインター用のメモリーを予約するために、そのアドレスに何があるかを知る必要はありません。
前方参照は、型を宣言するが定義しない場合です。
ポインタ(またはC ++の参照)で型を使用できますが、変数を宣言することはできません。
これは、何かが存在することをコンパイラに伝える方法です
Plop.h でPlop構造が定義されているとします:
struct Plop
{
int n;
float f;
};
ここで、その構造体で機能するユーティリティ関数をいくつか追加します。別のファイル PlopUtils.h を作成します(Plop.hを変更できないとしましょう):
struct Plop; // Instead of including Plop.h, just use a forward declaration to speed up compile time
void doSomething(Plop* plop);
void doNothing(Plop* plop);
これらの関数を実装するとき、構造定義が必要になるため、 PlopUtils.cpp にPlop.hファイルを含める必要があります。
#include "PlopUtils.h"
#include "Plop.h" // now we need to include the header in order to work with the type
void doSomething(Plop* plop)
{
plop->n ...
}
void doNothing(Plop* plop);
{
plop->f ...
}
Cコンパイラには元々、シンボルテーブルの構築とセマンティック分析を一緒に行うパスがあったと思います。例えば:
....
... foo(a,b) + 1 ... // assumes foo returns int
....
double foo(double x, double y){ ... } // violates earlier assumption
これを防ぐには、次のように言います:
double foo(double x, double y); // this is the forward declaration
....
... foo(a,b) + 1 ... // correct assumptions made
....
double foo(double x, double y){ ... } // this is the real declaration
Pascalにも同じ概念がありました。
以前の回答への追加。前方参照が必須である典型的な状況は、構造体fooが構造体barへのポインターを含み、バーがfoo(宣言間の循環依存関係)へのポインターを含む場合です。この状況をCで表現する唯一の方法は、前方宣言を使用することです。つまり:
struct foo;
struct bar
{
struct foo *f;
};
struct foo
{
struct bar *b;
};
前方参照により、Cコンパイラはより少ないパスを実行でき、コンパイル時間を大幅に短縮できます。おそらく20年ほど前にコンピューターが非常に遅くなり、コンパイラーの効率が低下したことが重要でした。