2017-10-31 1 views
2

質問

:CでCの構文は、後方参照と前方参照(ポインタ)を持つ自己完結型の静的に割り当てられた完全constデータ構造を定義できますか?私はこれらの制約を有するデータ構造を定義する必要が

  • (大丈夫C99)構造(構造体)インスタンスを含む構造のインスタンスの数を含みます他のポインタへのポインタ構造体のインスタンス(グラフ構造ですが、概念的にはの二重リンクリストで十分です)
  • 全体の構造は静的にコンパイル時に割り当て をしなければならない
  • (リンクされることを、メモリ内のアドレスではなく、完全なポインタを含む全体構造のメモリレイアウト)すべてのフィールドが定数を宣言されている
  • (ポインタ)前方ある
  • 一部参照、後方一部含みます。 IOWは、宣言を解析するときに、まだ解析されていないフィールドを参照するポインタもあります(しかし、構造体はコンパイラによって認識されているため、メモリ内のレイアウトはすでにわかっています)。
  • 移植性、標準準拠、大きなプラス。

enter image description here

あなたは、私はそれをやったが、私は躊躇して簡単なリファレンスを見つけないので、この質問は私の将来の自己と同じことを必要とするすべての人を助けるのに役立つ

を投稿する前に検索します。

メタファー

楽しい事実:すべてのこれらの制約に従うためには、段ボール箱の上部を折るように感じている:それは完了だ後、それはしっかりとフィットしますが、それはすべての部品を合わせて持っているか、それは動作しません。

Folding a cardboard box top.

(画像はhttps://www.youtube.com/watch?v=H5oOBLSJzGMクレジット)

答えて

3

Cの構文これを許可しません。

#include <stdio.h> 

// Let's say everything is const, so far, so good. 
typedef struct node_t 
{ 
     const int field; 
     const struct node_t *const previous; 
     const struct node_t *const next; 
} node_t; 

// Even simpler here. Const also. 
typedef struct graph_t 
{ 
     const struct node_t node1; 
     const struct node_t node2; 
     const struct node_t node3; 
} graph_t; 

// Where all falls into place. 
// The .node* labels are not necessary but may be useful for clarity. 
// The trick is to use the variable graph being defined. 
const graph_t graph = 
{ 
     .node1 = {1, &graph.node3, &graph.node2}, 
     .node2 = {2, &graph.node1, &graph.node3}, 
     .node3 = {3, &graph.node2, &graph.node1}, 
}; 

int main(int argc, char **argv) 
{ 
     (void)argc; 
     (void)argv; 
     printf("Value %d\n", graph.node2.field); 
     return 42; 
} 

コンパイル

gcc -Wall -W -pedantic a.c && ./a.out 
Value 2 

警告なし。

sdccと同じ結果です。

は、拘束されたシステムでいいですコードセクションでconstの土地であること

全体の構造体およびインスタンスを、利点。

+1

'ので' const'、あなたがnode1'、 'node2'、'ノード3 'から' const'修飾子を削除することができます'と'フィールド '。 'const struct node_t *'のような最初の 'const'修飾子を使わずに' previous'と 'next'を宣言することもできます。 – user694733

+0

@ user694733最初の部分(フィールド宣言から 'const'を削除する)が真になります。メリットは、一般的に書くことができるstructを定義することですが、特定の 'graph'インスタンスを書くことはできません。最後の部分は違うようです。 –

+0

あなたが書いたように正確に行うとき( '*'と 'previous'の間に' const'を削除する)、2番目の部分についても真です。他の 'const'を削除すると正当な警告が出ます。なぜなら' node_t'は 'const graph_t graph 'の一部である* const *であるstructを変更しないことを約束しないからです。微妙だが一貫性がある。ありがとう@ user694733。 –

1

私は以前と同じような問題を抱えていましたが、グラフの代わりにツリーを使用しました。私はあなた自身で提供されたソリューションを使用しましたが、ノード識別子などが混乱していましたので、プリプロセッサでそれらを処理するための素晴らしいソリューションが提供されました(Xマクロ)。私は私が提供された応答を共有するので、誰もがそれを使用することができます:graph`が宣言され

https://stackoverflow.com/a/22745618/3473433

+0

そこに興味深い変種。基本的に、私のソリューションはコンテナ構造体を使用しており、少なくともそれらの参照を必要とするメンバを指定する必要があります。しかし、コンパイル時間の後では、IDはkepsではありません(私はそれらを必要とせず、それらを必要としません)。 @ luserdroogの答えでは、あなたがすでに導入し使用しているIDで他のメンバーを参照することができます。ニースのXマクロも。 –

関連する問題