[英]Define struct field with circular reference
我有以下代碼,其中 struct 字段取決於尚未聲明的 struct 字段,因為該結構反過來可能取決於我嘗試聲明的結構。
我如何設計它以便它編譯? 或者我是否缺少一種擺脫聯合結構以將多個結構定義保持在一起的明顯方法?
typedef struct expression {
expression_type type;
union {
bool_expression bool;
identifier_expression ident;
integer_expression _int;
prefix_expression prefix;
infix_expression infix;
// TODO: Fix this
if_expression _if;
};
} expression;
typedef struct statement {
token token;
identifier name;
expression * value;
} statement;
typedef struct block_statement {
token token;
statement *statements;
} block_statement;
typedef struct if_expression {
token token;
expression condition;
block_statement *consequence;
block_statement *alternative;
} if_expression;
在這種情況下,你不能。
if_expression
包含一個expression
,而該expression
又包含一個if_expression
。 如果您通過使用指針解決這個問題,您可以重新排列您的定義並使用struct expression*
創建一個指向尚未定義的結構的指針。
如果你改變了expression condition;
expression *condition;
在if_expression
,和前向聲明expression
— typedef struct expression expression;
在頂部,然后放置struct expression { … };
在底部,代碼應該沒問題。
/* Placeholder typedefs for undefined typedef names */
typedef int token;
typedef int identifier;
typedef int bool_expression;
typedef int identifier_expression;
typedef int integer_expression;
typedef int prefix_expression;
typedef int infix_expression;
typedef int expression_type;
/* The fixed code starts here */
typedef struct expression expression;
typedef struct statement
{
token token;
identifier name;
expression * value;
} statement;
typedef struct block_statement
{
token token;
statement *statements;
} block_statement;
typedef struct if_expression
{
token token;
expression *condition;
block_statement *consequence;
block_statement *alternative;
} if_expression;
struct expression
{
expression_type type;
union
{
bool_expression bool;
identifier_expression ident;
integer_expression _int;
prefix_expression prefix;
infix_expression infix;
if_expression _if;
};
};
expression expr = { 0 };
這編譯。
您最好至少在最初刪除typedefs
,以便您可以更好地了解您的類型。
您應該將結構更改為指向(而不是包含)其他結構,例如:
struct if_expression {
/* struct? */ token *token;
struct expression *condition;
struct block_statement *consequence;
struct block_statement *alternative;
}
當然,這會強制使用malloc()
和free()
調用。 在某些情況下,您可以稍后恢復為包含(如上面的token
,因為預計它不會指向您的其他結構,並且復制標記可能是一種廉價的操作)。
對於引用的循環性,您可以在 C 中轉發聲明,即您告訴編譯器“嘿,有一個名為表達式的結構體,您還不知道其內部結構,但請耐心等待,您很快就會知道的”:
struct expression;
如果您以后決定使用typedef
- 這樣您的代碼就會變得更加精簡 - 請記住,結構可以有一個名稱,並且 typedef 定義名稱,並且這些名稱不共享相同的名稱空間。 在示例中:
typedef struct {
/* ...internal structure omited... */
} type_a;
typedef struct type_b {
/* ...internal structure omited... */
} type_b;
typedef struct struct_c {
/* ...internal structure omited... */
} type_c;
這里type_a
是一個定義為匿名結構的類型。 而type_b
是定義為struct type_b
的類型,即命名( type_b
)結構。 而type_c
是定義為struct struct_c
的類型,即命名( struct_c
)結構。
現在把它們放在一起,你可以:
/* forward all your structs */
struct expression;
struct if_expression;
struct block_statement;
/* typedef them all */
typedef struct expression expression;
typedef struct if_expression if_expression;
/* actually define them */
struct expression {
/* ... */
}
作為腳注,通過了解聲明和定義之間的區別,您可以了解很多關於 C 語言的知識。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.