[英]Why is “typedef struct foo foo;” considered harmful?
In typedef and struct namespaces in C vs C++ , one of the comments seems to imply that exposing some struct foo
is preferable to using typedef along the lines of...在C 与 C++ 中的 typedef 和 struct 命名空间中,其中一条注释似乎暗示暴露一些
struct foo
比使用 typedef 更可取...
typedef struct foo foo;
...and then using foo
instead of struct foo
throughout the API. ...然后在整个 API 中使用
foo
而不是struct foo
。
Are there any downsides to the latter variant?后一种变体有什么缺点吗?
The only downside(*) is that it hides the fact that foo
is a struct, and not an alias for some builtin type.唯一的缺点 (*) 是它隐藏了
foo
是结构体而不是某些内置类型的别名的事实。
Note(*): it's matter of taste whether this is a downside for you.注意(*):这是否对您不利是品味问题。
It depends how much you like the word struct
.这取决于您有多喜欢
struct
一词。 If you feel your program will be made clearer by a liberal sprinkling of struct that
and struct tother
(you can't have struct this
in C++, of course), then by all means use the struct
version.如果您觉得通过
struct tother
struct that
和struct tother
您的程序更加清晰(当然,您不能在 C++ 中使用struct this
),那么请struct tother
使用struct
版本。
Personally, I don't think that repeating struct
provides any benefit and I'm happy to use just the typedef
name.就我个人而言,我认为重复
struct
没有任何好处,我很高兴只使用typedef
名称。 And because C++ effectively provides the typedef struct xyz xyz;
并且因为 C++ 有效地提供了
typedef struct xyz xyz;
declaration automatically (it isn't quite accurate, not least because you can explicitly write that in C++, but it is close enough that you probably don't have to worry about it), I think it makes perfect sense to use the same in C. The C compiler is happy with it, so I normally use typedef struct tag tag;
自动声明(它不太准确,尤其是因为您可以在 C++ 中明确地编写它,但它足够接近,您可能不必担心),我认为在C. C 编译器对它很满意,所以我通常使用
typedef struct tag tag;
and then use tag
and tag *
where needed.然后在需要的地方使用
tag
和tag *
。
For an alternative but wholly tenable view, read the Linux kernel coding style guide.对于另一种但完全站得住脚的观点,请阅读Linux 内核编码风格指南。
Note that C2011 allows you to redefine a typedef
as long as it aliases the same type:请注意,C2011 允许您重新定义
typedef
,只要它具有相同类型的别名:
ISO/IEC 9899:2011 §6.7 Declarations
ISO/IEC 9899:2011 §6.7 声明
Semantics
语义
¶5 A declaration specifies the interpretation and attributes of a set of identifiers.
¶5 声明指定了一组标识符的解释和属性。 A definition of an identifier is a declaration for that identifier that:
标识符的定义是对该标识符的声明:
— for an object, causes storage to be reserved for that object;
— 对于一个对象,导致为该对象保留存储空间;
— for a function, includes the function body;
——对于函数,包括函数体; 119)
119)
— for an enumeration constant, is the (only) declaration of the identifier;
— 对于枚举常量,是标识符的(唯一)声明;
— for a typedef name, is the first (or only) declaration of the identifier.
— 对于 typedef 名称,是标识符的第一个(或唯一)声明。
Contrast with C99 where this was not possible:与 C99 相比,这是不可能的:
Semantics
语义
¶5 A declaration specifies the interpretation and attributes of a set of identifiers.
¶5 声明指定了一组标识符的解释和属性。 A definition of an identifier is a declaration for that identifier that:
标识符的定义是对该标识符的声明:
— for an object, causes storage to be reserved for that object;
— 对于一个对象,导致为该对象保留存储空间;
— for a function, includes the function body;
——对于函数,包括函数体; 98)
98)
— for an enumeration constant or typedef name, is the (only) declaration of the identifier.
— 对于枚举常量或 typedef 名称,是标识符的(唯一)声明。
This simplifies the creation of type definitions as long as you're consistent (but only if you have a sufficiently compatible C2011 compiler on each platform of relevance to you).只要您保持一致(但前提是您在与您相关的每个平台上都有足够兼容的 C2011 编译器),这会简化类型定义的创建。
On whether or not to typedef structure types:关于是否要 typedef 结构类型:
Here is some opinions around (all against typedefing structures):以下是一些意见(都反对 typedefing 结构):
From OpenBSD style guide:来自 OpenBSD 风格指南:
"Avoid using typedefs for structure types. This makes it impossible for applications to use pointers to such a structure opaquely, which is both possible and beneficial when using an ordinary struct tag."
“避免对结构类型使用 typedef。这使得应用程序不可能不透明地使用指向这种结构的指针,这在使用普通结构标记时既可能又有益。”
From Linux kernel coding style:来自 Linux 内核编码风格:
"It's a mistake to use typedef for structures and pointers."
“将 typedef 用于结构和指针是错误的。”
From Expert C Programming by Peter Van der Linden:来自 Peter Van der Linden 的 Expert C Programming:
"Don't bother with typedefs for structs. All they do is save you writing the word "struct", which is a clue that you probably shouldn't be hiding anyway."
“不要为结构体的 typedef 烦恼。他们所做的只是让你不用写“结构体”这个词,这是一个你可能不应该隐藏的线索。”
It's more or less a matter of taste.这或多或少是品味问题。
By just declaring a struct
tag, the name is also available to be used for variables, functions, or enumerators in the same scope (or even another type, if you enjoy confusion);通过声明一个
struct
标签,该名称也可用于同一范围内的变量、函数或枚举数(或者甚至是另一种类型,如果你喜欢混淆); and users must write the word struct
, which makes their code more explicit.并且用户必须编写单词
struct
,这使他们的代码更加明确。
By also declaring a type name, you allow people not to type struct
if they don't want to.通过同时声明类型名称,您可以允许人们在他们不想时不要输入
struct
。
My comment in the other question was referring to the declaration of a pointer type with the same name as the struct tag:我在另一个问题中的评论是指与结构标记同名的指针类型的声明:
typedef struct foo * foo;
Stylistically, this is slightly unpleasant because it hides the fact that it's a pointer.在风格上,这有点令人不快,因为它隐藏了它是一个指针的事实。 This hides the fact that it is a pointer;
这隐藏了它是一个指针的事实; that is perhaps fine in the context of that question, where this is an opaque type defined by an API, but in my opinion would be rather rude for a non-opaque type.
在该问题的上下文中,这可能没问题,这是由 API 定义的不透明类型,但在我看来,对于非不透明类型来说,这将是相当粗鲁的。 It also breaks compatibility with C++.
它还破坏了与 C++ 的兼容性。 In that language, such a declaration is invalid, since
struct foo
introduces foo
into the current namespace rather than a separate tag space, and prevents the declaration of any other type with the same name in that namespace.在该语言中,这样的声明是无效的,因为
struct foo
将foo
引入当前命名空间而不是单独的标记空间,并防止在该命名空间中声明任何其他具有相同名称的类型。
Just stick to a naming convention and you'll be fine.只要坚持命名约定,你就会没事的。
typedef struct
{
//...
} t_mytype;
//...
t_mytype thing;
This way you'll know it's a custom type.这样你就会知道它是一个自定义类型。 As for it being a struct, just use explicit names and not really
t_mytype
至于它是一个结构,只需使用显式名称而不是真正的
t_mytype
One another argument against typedef is the difficulty it write clean headers.另一个反对 typedef 的论点是它编写干净的标头的难度。 Let's see an example of header:
让我们看一个标题的例子:
#ifndef HEADER_H
#define HEADER_H
#include "s.h"
void f(struct s *);
#endif
This header can be improved.这个标题可以改进。 Indeed,
struct s
does not need to be defined.实际上,
struct s
不需要定义。 So it could be written:所以可以写成:
#ifndef HEADER_H
#define HEADER_H
struct s;
void f(struct s *);
#endif
Thus, the user may use struct s
as an opaque struct and we can keep "sh"
private.因此,用户可以使用
struct s
作为一个不透明的结构,我们可以保持"sh"
私有。
Let's do the same thing but with typedef
:让我们用
typedef
做同样的事情:
#ifndef HEADER_H
#define HEADER_H
typedef struct s s_t;
void f(s_t *);
#endif
The line typedef struct s s_t
will appears in every header that want to use s_t *
and I dislike redundant code.行
typedef struct s s_t
将出现在每个想要使用s_t *
标题中,我不喜欢冗余代码。 There are multiple ways to avoid that, but the easiest is probably to get rid of typedef.有多种方法可以避免这种情况,但最简单的方法可能是摆脱 typedef。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.