在C语言中声明结构体:为什么我需要两次指定名称?

3
为了在C中声明一个结构体,我一直使用以下代码:
typedef struct Foo Foo;

然后在下方某个位置定义它。

为什么我要两次指定结构体的名称 (Foo)?


2
这并不是在声明一个结构体。你可以避免这样做,使用完整的 struct Foo 类型名称。一些代码指南甚至将其作为原则。 - StoryTeller - Unslander Monica
3个回答

2

struct Foo 是正在创建新类型别名的类型。最后一个 Foo 是新类型的名称。如果您的结构声明可见,则可以像这样编写类型定义和结构声明组合,以避免重复的 Foo

typedef struct {
  ...
} Foo;

不是我的DV,但只有在“struct”定义可见的情况下才能起作用。对于不透明的“struct”,它不起作用。 - Andrew Henle
我会在上面做注释,谢谢。个人而言,我喜欢使用独立的命名空间,所以我认为我从来没有使用过typedef。 - Allan Wind
@AndrewHenle “DV” 代表什么? - Allan Wind
你之前有一个“DV”,意思是“downvote”。 - Andrew Henle
1
@AndrewHenle 当然啦。就算是这样,没关系,我还是喜欢你的 :-) - Allan Wind

2
格式是:
typedef old_type new_type

so for

typedef struct Foo Foo;

struct Foo 是旧类型,Foo 是新类型,因此无论何时您键入 Foo,它实际上是 struct Foo 的别名。


哦,好的。那么typedef和#define有什么区别呢?(当然,这可能值得单独提问,但是在这里简单解释一下是否足够?)谢谢! - Robbie

0

您不必指定两个名称。您可以像这样介绍一个不完整的结构体类型:

struct Foo;

就是这样。或者一个完整的:

struct Foo { int x; };

这些声明都不会将名称引入作用域,它们只是引入了一个结构体的tag

如果您引入了一个结构体标签,那么您必须在任何地方使用struct关键字来引用它,例如:

struct Foo f;

void fun(struct Foo *param);

typedef 的作用是避免在每个地方都需要编写 struct Foo。类型名称可以不同于标记:

typedef struct Foo_s Foo;

Foo f;
void fun(Foo *param);

C++方言改变了规则;在C++中,struct Foo引入了Foo作为类型名称和标签(用于C兼容性)。

你可能会看到typedef struct Foo Foo的一个原因是代码最初是以C++形式编写的,看起来像这样:

struct Foo;              // Originally C++ only header file.
void fun(Foo *param);

然后出现了一个要求,即必须支持C语言,至少在头文件中。在C语言中,Foo类型没有声明:

typedef struct Foo Foo;  // Fix for C.

#ifdef __cplusplus
#define extern_c extern "C"   // C compatible linkage for fun
#endif

void fun(Foo *param);

#ifdef __cplusplus
}
#endif

虽然在这方面C++可能看起来更方便,但它的对象系统绝对会惩罚用户,因为会重复相同的标识符,你简直无法想象。

要定义一个基本的类骨架,并且构造函数和析构函数不在类声明中内联,我们必须重复七次名称:

class foo {
public:
  foo();
  ~foo();
}; 

foo::foo()
{
}

foo::~foo()
{
}

幸好C ++程序员至少被免于在任何地方编写 class foo * fooptr ,对吧?


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