2

循環リンクが必要な C/C++ データ構造を静的に定義するための最もよく知られた方法を探しています。たとえば、子と親の両方が相互へのポインターを必要とするツリー。

extern struct Op op_subops[4]; // fwd ref to children of ops

struct Op
{
    const char *name;
    struct Op  *parent;
    struct Op  *children;
};


struct Op ops[128] = {
    {"op",0,&op_subops[0]}
};

struct Op op_subops[4] = {
    {"subop1",&ops[1],0},
    {"subop2",&ops[1],0}
};

上記はコンパイルされます (g++ 5.2)。キーワードにより、からへexternの前方参照を作成できるように思われます。また、逆の方向は、先行するため、自然に機能します。opsops_subopsopsops_subops

私が気に入らないのは、両方の配列がそうであることを好むということですstatic(オブジェクトファイルに公に見えるシンボルを作成しないでください)。

方向の 1 つに整数インデックスを使用することもできますが、それはちょっとばかげているように思えます。リンカにアドレスを解決してもらいたいだけです。

これを機能させるための魔法のキーワードを持っている人はいますか?

ありがとう!

編集: C++ 静的コンストラクターや最先端の​​ C++17 拡張機能などを避ける必要があります (悲しいことに)。そして、私のアプローチはプラットフォームに依存しない必要があります。

4

2 に答える 2

2

C と C++ のどちらでも、宣言する前にオブジェクトを参照することはできませんが、どちらの言語でも、オブジェクトを定義せずに名前と (おそらく不完全な) 型を宣言する「前方宣言」を記述できます。C に精通しているので、その観点からお答えします。一部のセマンティクスは C++ では異なる場合があります。

C では、提示したコードの主な問題は、配列の要件に違反することです。

要素の型は、配列型が指定されているときはいつでも完全でなければなりません。

(C2011、6.2.5/20)

つまり、サイズなしで配列を前方宣言することはできますが(その意味でその型は不完全なままです)、型が定義されるop_subops前にその宣言を発行することはできません。struct Opこれは、2 つの宣言の位置を交換するだけで解決できます。

static順序付けの問題を修正したので、C では両方の配列をリンケージで宣言してもまったく問題ありません。オブジェクトが複数回宣言されている場合 (つまりop_subops)、すべての宣言がそのリンケージについて一致していることを確認する必要があります。

struct Op
{
    const char *name;
    struct Op  *parent;
    struct Op  *children;
};

static struct Op op_subops[4]; // fwd ref to children of ops

static struct Op ops[128] = {
    {"op",0,&op_subops[0]}
};

static struct Op op_subops[4] = {
    {"subop1",&ops[0],0},
    {"subop2",&ops[1],0}
};

必要に応じて、最初の宣言からの長さを省略できop_subopます。実際、2 つの宣言で長さの一貫性を維持する必要がないように、そうすることをお勧めします。

あなたは「最善の[既知の]方法」を求めていますが、それは文脈によって色付けされた意見の問題であり、意見の質問はここでは話題から外れています. 一方、この場合、子の配列が必要なようです。そのため、型を変更せずに他にどのような選択肢があるかわかりません。

于 2016-10-31T18:41:44.360 に答える