为什么“typedef struct foo foo;”认为有害吗?

时间:2012-04-20 08:59:11

标签: c coding-style

typedef and struct namespaces in C vs C++中,其中一条评论似乎暗示暴露某些struct foo比使用typedef更好...

typedef struct foo foo;

...然后在整个API中使用foo代替struct foo

后一种变体是否有任何缺点?

6 个答案:

答案 0 :(得分:9)

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

注意(*):这对你来说是不是一个缺点。

  • 这对完全不透明有好处(见下面的第一条评论)。
  • 要了解为什么有些人认为这是一个缺点,请查看linux kernel coding style(typedefs章节)。

答案 1 :(得分:8)

这取决于您对单词struct的喜爱程度。如果你觉得你的程序会因为struct thatstruct 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相比,这是不可能的:

ISO / IEC 9899:1999§6.7声明

  

<强>语义

     

¶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 foofoo引入当前命名空间而不是单独的标记空间,并且阻止在该命名空间中声明具有相同名称的任何其他类型。 / 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。