12

C 与 C++ 中的 typedef 和 struct 命名空间中,其中一条评论似乎暗示暴露一些struct foo比使用 typedef 更可取...

typedef struct foo foo;

...然后在整个 API 中使用foo而不是使用。struct foo

后一种变体有什么缺点吗?

4

6 回答 6

9

唯一的缺点(*)是它隐藏了foo一个结构的事实,而不是某些内置类型的别名。

注意(*):这是否对您不利,这取决于您的口味。

  • 它有利于完全不透明(见下面的第一条评论)。
  • 要了解为什么有些人认为这是一个缺点,请查看linux 内核编码风格(typedefs 章节)。
于 2012-04-20T09:03:44.217 回答
8

这取决于你有多喜欢这个词struct。如果你觉得你的程序会通过自由洒struct thatstruct tother(当然你不能struct this在 C++ 中)使你的程序更清晰,那么一定要使用这个struct版本。

就个人而言,我不认为重复struct提供任何好处,我很高兴只使用这个typedef名字。而且因为 C++typedef struct xyz xyz;自动有效地提供了声明(它不是很准确,尤其是因为你可以用 C++ 显式编写它,但它足够接近,你可能不必担心它),我认为它是完美的在 C 中使用相同的东西是有意义的。C 编译器对此很满意,所以我通常使用typedef struct tag tag;然后在需要的地方使用tag和。tag *


如需另一种但完全站得住脚的观点,请阅读Linux 内核编码风格指南。


请注意,C2011 允许您重新定义 a typedef,只要它别名相同的类型:

ISO/IEC 9899:2011 §6.7 声明

语义

¶5 声明指定一组标识符的解释和属性。标识符的定义是该标识符的声明:

— 对于一个对象,导致为该对象保留存储空间;

— 对于函数,包括函数体;119)

— 对于枚举常量,是标识符的(唯一)声明;

— 对于 typedef 名称,是标识符的第一个(或唯一一个)声明。

与 C99 相比,这是不可能的:

ISO/IEC 9899:1999 §6.7 声明

语义

¶5 声明指定一组标识符的解释和属性。标识符的定义是该标识符的声明:

— 对于一个对象,导致为该对象保留存储空间;

— 对于函数,包括函数体;98)

— 对于枚举常量或 typedef 名称,是标识符的(唯一)声明。

只要您保持一致,这就会简化类型定义的创建(但前提是您在与您相关的每个平台上都有足够兼容的 C2011 编译器)。

于 2012-04-20T09:12:18.953 回答
7

关于是否 typedef 结构类型:

这里有一些意见(都反对 typedefing 结构):

来自 OpenBSD 风格指南:

“避免对结构类型使用 typedef。这使得应用程序不可能不透明地使用指向这种结构的指针,这在使用普通结构标记时既可行又有益。”

从 Linux 内核编码风格:

“将 typedef 用于结构和指针是错误的。”

来自 Peter Van der Linden 的 Expert C Programming:

“不要为结构体的 typedefs 烦恼。他们所做的只是省去你写“结构体”这个词的麻烦,这是一个你可能不应该隐藏的线索。

于 2012-04-20T09:19:16.643 回答
2

这或多或少是一个品味问题。

通过仅声明一个struct标签,该名称也可用于同一范围内的变量、函数或枚举器(如果您喜欢混淆,甚至可以是另一种类型);并且用户必须写这个词struct,这使得他们的代码更加明确。

通过还声明类型名称,您可以允许人们在不想键入struct时不键入。

我在另一个问题中的评论是指与结构标记同名的指针类型的声明:

typedef struct foo * foo;

从风格上讲,这有点令人不快,因为它隐藏了它是指针的事实。这隐藏了它是一个指针的事实;在那个问题的上下文中,这可能很好,这是由 API 定义的不透明类型,但在我看来,对于非透明类型来说是相当粗鲁的。它还破坏了与 C++ 的兼容性。在那种语言中,这样的声明是无效的,因为struct foo引入foo了当前命名空间而不是单独的标记空间,并防止在该命名空间中声明任何其他具有相同名称的类型。

于 2012-04-20T09:13:15.797 回答
1

只要坚持命名约定,你就会没事的。

typedef struct
{
  //...
}              t_mytype;
//...
t_mytype thing;

这样你就会知道它是一个自定义类型。至于它是一个结构,只需使用显式名称而不是真正使用t_mytype

于 2012-04-20T09:06:20.487 回答
0

反对 typedef 的另一个论点是它编写干净的标头的难度。让我们看一个标题的例子:

#ifndef HEADER_H
#define HEADER_H
#include "s.h"
void f(struct s *);
#endif

这个标题可以改进。确实,struct s不需要定义。所以可以写成:

#ifndef HEADER_H
#define HEADER_H
struct s;
void f(struct s *);
#endif

因此,用户可以使用struct s不透明的结构,我们可以保持"s.h"私有。

让我们做同样的事情,但使用typedef

#ifndef HEADER_H
#define HEADER_H
typedef struct s s_t;
void f(s_t *);
#endif

该行将typedef struct s s_t出现在每个要使用的标题中,s_t *我不喜欢冗余代码。有多种方法可以避免这种情况,但最简单的可能是摆脱 typedef。

于 2021-03-31T09:49:57.077 回答