繁体   English   中英

使用循环引用定义结构字段

[英]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 ,和前向声明expressiontypedef 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM