在typedef and struct namespaces in C vs C++中,其中一条评论似乎暗示暴露某些struct foo
比使用typedef更好...
typedef struct foo foo;
...然后在整个API中使用foo
代替struct foo
。
后一种变体是否有任何缺点?
答案 0 :(得分:9)
唯一的缺点是(*)隐藏了foo
是结构的事实,而不是某些内置类型的别名。
注意(*):这对你来说是不是一个缺点。
答案 1 :(得分:8)
这取决于您对单词struct
的喜爱程度。如果你觉得你的程序会因为struct that
和struct tother
(你当然不能在{+ 1}中使用struct this
)而更加清晰,那么请务必使用{ {1}}版本。
就个人而言,我认为重复struct
不会带来任何好处,我很乐意只使用struct
名称。并且因为C ++有效地自动提供typedef
声明(它不是很准确,尤其是因为你可以在C ++中明确地写出它,但它足够接近你可能不必担心它),我认为在C语言中使用它是完全合理的.C编译器很满意它,所以我通常使用typedef struct xyz xyz;
然后在需要时使用typedef struct tag tag;
和tag
。
有关替代但完全可行的观点,请阅读Linux kernel coding style指南。
请注意,C2011允许您重新定义tag *
,只要它为同一类型别名:
ISO / IEC 9899:2011§6.7声明
<强>语义强>
¶5声明指定一组标识符的解释和属性。一个定义 标识符是该标识符的声明:
- 对于一个对象,导致为该对象保留存储;
- 对于一个函数,包括函数体; 119)
- 对于枚举常量,是标识符的(唯一)声明;
- 对于typedef名称,是标识符的第一个(或唯一)声明。
与C99相比,这是不可能的:
<强>语义强>
¶5声明指定一组标识符的解释和属性。一个定义 标识符是该标识符的声明:
- 对于一个对象,导致为该对象保留存储;
- 对于一个函数,包括函数体; 98)
- 对于枚举常量或typedef名称,是(唯一)声明 标识符
只要您保持一致(但只有在与您相关的每个平台上都有足够兼容的C2011编译器),这才能简化类型定义的创建。
答案 2 :(得分:6)
关于是否输入结构类型:
以下是一些意见(所有针对typedefing结构):
来自OpenBSD风格指南:
&#34;避免对结构类型使用typedef。这使得应用程序不可能不透明地使用指向这种结构的指针,这在使用普通的struct标签时既可能又有益。&#34;
从Linux内核编码风格:
&#34; 错误将typedef用于结构和指针。&#34;
来自Peter Van der Linden的专家C编程:
&#34;不要为结构的typedef烦恼。他们所做的只是为你写下“#34; struct&#34;”这个词,这是你可能不应该隐藏的线索。&#34;
答案 3 :(得分:2)
这或多或少是品味问题。
通过声明struct
标记,该名称也可用于同一范围内的变量,函数或枚举数(如果您喜欢混淆,则可用于其他类型);并且用户必须编写单词struct
,这使他们的代码更加明确。
通过声明类型名称,您可以允许用户不要键入struct
。
我在另一个问题中的评论是指一个指针类型的声明,其名称与struct标签相同:
typedef struct foo * foo;
在风格上,这有点令人不愉快,因为它隐藏了它是指针的事实。这隐藏了它是指针的事实;在这个问题的上下文中,这可能很好,这是一个由API定义的opaque类型,但在我看来,对于非opaque类型来说,这是相当粗鲁的。它还打破了与C ++的兼容性。在该语言中,这样的声明是无效的,因为struct foo
将foo
引入当前命名空间而不是单独的标记空间,并且阻止在该命名空间中声明具有相同名称的任何其他类型。 / p>
答案 4 :(得分:1)
坚持命名惯例,你会没事的。
typedef struct
{
//...
} t_mytype;
//...
t_mytype thing;
这样你就会知道它是一种自定义类型。至于它是一个结构,只使用显式名称而不是t_mytype
答案 5 :(得分: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。