[英]Initializing constant struct containing pointer to its own type
我有這樣的結構:
typedef struct tree_s{
struct tree_s *a;
int b;
}tree_t;
目前,我正在以這種方式初始化:
tree_t branch_n = {
.a = NULL,
.b = 2
};
tree_t root = {
.a = (tree_t*) &branch_n,
.b = 1
};
現在,讓我感到惱火的是我必須在root之前初始化較低的分支,因為完整的結構非常大,分支有自己的分支,使我的代碼難以管理。
我想做的是這樣的事情:
tree_t root = {
.a =
//The first branch
{
.a =
//Yet another branch
{ //Since the following is actually an array, I need the
// "a" above to point to the first index
{
.a = NULL, //Maybe this will have its own branch
.b = 3
},
{
.a =
{
.a = NULL, //And this might even have its own branch
.b = 5
}
.b = 4
}
}
.b = 2
},
.b = 1
};
我怎樣才能實現這樣的初始化?
我想這樣做的主要原因是為了大大增強我的代碼的概述,並立即直觀地看到“樹”的結構。
請注意,從一開始就知道完整“樹”的結構,這就是我認為結構不變的原因。 然而,值b可以隨時改變。
我是C語言的新手,這是我關於SO的第一篇文章,所以請隨時編輯或詢問我是否能夠讓自己明白:)
您的“樹”結構似乎卡在一個相當線性的形狀,但您可以使用數組來解決問題:
static const tree_t oak[] =
{
{ .a = &oak[1], .b = 20 },
{ .a = &oak[2], .b = 15 },
{ .a = NULL, .b = 10 },
};
或者給出二叉搜索樹結構:
#include <stdio.h>
typedef struct bst_t bst_t;
struct bst_t
{
int data;
const bst_t *left;
const bst_t *right;
};
static const bst_t bst[] =
{
{ .data = 30, .left = &bst[1], .right = &bst[2] },
{ .data = 10, .left = &bst[3], .right = &bst[4] },
{ .data = 50, .left = &bst[5], .right = &bst[6] },
{ .data = 5, .left = &bst[7], .right = &bst[8] },
{ .data = 20, .left = 0, .right = &bst[9] },
{ .data = 40, .left = 0, .right = 0 },
{ .data = 60, .left = 0, .right = 0 },
{ .data = 2, .left = 0, .right = 0 },
{ .data = 8, .left = 0, .right = 0 },
{ .data = 28, .left = 0, .right = 0 },
};
static void print_in_order(const bst_t *bst)
{
if (bst != 0)
{
printf("[");
print_in_order(bst->left);
printf("(%d)", bst->data);
print_in_order(bst->right);
printf("]");
}
}
static void print_tree(const bst_t *bst)
{
print_in_order(bst);
putchar('\n');
}
int main(void)
{
print_tree(&bst[0]);
return 0;
}
這會產生輸出:
[[[[(2)](5)[(8)]](10)[(20)[(28)]]](30)[[(40)](50)[(60)]]]
使用C99和復合文字,您可以編寫:
#include <stddef.h>
typedef struct tree_s{
struct tree_s *a;
int b;
}tree_t;
tree_t root2 =
{
.a = &(tree_t){ .a = NULL, .b = 2 }, .b = 1
};
tree_t root3 =
{
.a = &(tree_t){ .a = &(tree_t){ .a = NULL, .b = 3 }, .b = 2 }, .b = 1
};
我不確定它是否清晰,但它編譯好。 總的來說,我更喜歡數組符號。
這是OP想要/使用的主要答案。
嘗試修改有問題的修改后的數據結構(請記住,可以使用數據結構創建的“樹”只是一個單鏈表),你幾乎可以(但不是完全)用這個來做:
tree_t root4 =
{
.a = &(tree_t)
{
.a = (tree_t [])
{
(tree_t){
.a = NULL,
.b = 3
},
(tree_t){
.a = &(tree_t)
{
.a = NULL,
.b = 5
},
.b = 4
},
}, // Line 47
.b = 2
},
.b = 1
};
GCC(i686-apple-darwin11-llvm-gcc-4.2(GCC)4.2.1(基於Apple Inc. build 5658)(LLVM build 2336.11.00))在Mac OS X 10.8.4上抱怨:
tree.c:47: error: initializer element is not constant
tree.c:47: error: (near initialization for ‘(anonymous)’)
標記第47行的地方 - 它是結構數組的末尾。 我可能會遺漏一些明顯的東西。 我確實試過&(test_t[]){ ... }[0],
但是得到了同樣的警告。
我完全不確定如何判斷特定指針是指向數組開頭而不是單個tree_t
元素的指針,除非您添加另一個字段來指示差異(或者b
字段以某種方式編碼以指示a
是指向單個項的指針還是指向數組的指針。
我不認為這段代碼:
tree_t root = {
.a =
//The first branch
{
.a = NULL, //Maybe another branch instead of NULL
.b = 2
},
.b = 1
};
將成功初始化tree_t根目錄。
{}用於初始化結構,而不是指針。 但root-> a被定義為指針。 您可能會因此而編譯錯誤。
可以在上面的代碼之外定義和初始化分支,並將指針root->設置為它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.