C语言中的自引用结构体

4

我正在尝试将在VS2010中编译良好的C++代码移植到c(gcc c99),但是我遇到了编译错误。这与其他自引用结构体问题有些不同,因为我有两个用户定义类型,每个类型都包含对彼此的指针。似乎我的前向声明不够。

struct potato; //forward declare both types
struct tomato;

struct potato
{
    potato* pPotato; //error: unknown type name ‘potato’
    tomato* pTomato;

};

struct tomato
{
    potato* pPotato;
    tomato* pTomato;
};

为什么这段代码在gcc 99中不能正常运行?作为C++代码它为什么可以?我该如何修改才能获得与c99相同的行为?


1
什么是错误? - DollarAkshay
编辑以显示错误行的内容 - user2864293
3个回答

8

或者,将它们都定义为typedef

typedef struct potato potato; //forward declare both types
typedef struct tomato tomato;

struct potato
{
    potato* pPotato;
    tomato* pTomato;

};

struct tomato
{
    potato* pPotato;
    tomato* pTomato;
};

5

自引用类型在C语言中是有效的,但在C语言中struct与变量/常量存在不同的命名空间,因此在使用其名称时必须在前面加上struct前缀。

此外,避免使用匈牙利命名法,对于您的情况,应避免使用p前缀。

尝试这样做:

struct potato; //forward declare both types
struct tomato;

struct potato
{
    struct potato* potato;
    struct tomato* tomato;

};

struct tomato
{
    struct potato* potato;
    struct tomato* tomato;
};

传统的避免不断输入 struct foo 的方法是使用 typedef
typedef struct potato potato;
< p > struct potato 的定义可以匿名和内联使用: < /p >
typedef struct { ... } potato;

我个人观察到,使用 typedef struct 的情况似乎正在减少,而在使用时总是指定 struct 的“长手写法”再次流行起来。


现今,匈牙利命名法被认为是不受欢迎的吗?为什么你建议避免使用它呢? - user2864293
1
@user2864293,因为它会影响可读性并且不提供任何有用的信息。你的编译器和IDE已经知道类型是什么,所以只需将鼠标悬停在名称上即可获得更多信息。 - Dai
@user2864293,这也会影响可维护性:如果你正在使用 C++,并且有一个原始指针并决定将其更改为智能指针,则必须重命名您在使用它们的地方处处出现的 pptr 前缀。 - Dai
我认为它应该可以在没有前向声明的情况下工作。 - Petr Skocik

1
你需要


struct potato
{
    struct potato* pPotato;
    struct tomato* pTomato;

};

普通的C语言不会自动定义结构体类型。

个人而言,我喜欢自动定义(我使用一个简短的后缀来表示typedef是一个结构体),所以我一直在用宏模拟它:

#define Struct(Nam,...) typedef struct Nam Nam; struct Nam __VA_ARGS__

Struct(tomato,);
Struct(potato,);

Struct( potato, {
    potato* pPotato; //error: unknown type name ‘potato’
    tomato* pTomato;

});

Struct(tomato, {
    potato* pPotato;
    tomato* pTomato;
});

tomato tom;
potato pot;

如果我想要包含一个typedef,这样我就不必修改其余代码中有很多土豆和番茄没有“struct”前缀的部分,该怎么办? - user2864293
@user2864293 我个人使用一个宏来在每个结构体定义前添加typedef。我已经将其添加到答案中。 - Petr Skocik
这取决于gcc扩展(允许没有参数匹配“,…”)。 - M.M
@M.M 在前向声明中添加了逗号。(实际上我以前从未使用过它来进行前向声明。我只是用它来定义,以便自动添加typedef)。 - Petr Skocik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接