Typedef 在结构和枚举上有或没有类型名,每个 pro/cons 是什么,最佳实践是什么?

Typedef with or without typename on structs and enum, what are pro/cons for each and what is best practice?

编辑:关于关闭基于意见的问题。 我专门钓鱼任何严格 objective 而不是主观性的东西。如果没有 objective 差异,那么说明如此的答案将得到复选标记。不过似乎存在明确的 objective 差异。


关于如何以及为什么在 C 中使用 typedef 包含在 SO 上的许多问题中,但是 none 似乎描述了应该使用哪个用例,或者每个用例的 pro/cons。

关于这个主题的大多数问题都围绕着这个

struct Bar {
    int value;
};

struct Foo {
    int value;
};
typedef struct Foo Foo;

struct Bar mybar; // Have to add keyword struct for it to work
Foo myfoo;        // Works without struct keyword

我的问题更多是最佳做法是什么,或者出于何种原因应该避免什么?使用以下任何示例会不会有问题?或者如果由于上下文而导致不同的答案,给定示例

的pro/cons是什么
// 1
typedef struct {
    int value;
} Foo;
// 2
typedef struct Foo {
    int value;
} Foo;
// 3
typedef struct Foo_s {
    int value;
} Foo_t;
// 4
typedef struct Foo {
    int value;
} Foo_t;

是否应该避免其中的任何一种,为什么?如果其中任何一个不太好,那么相同的精确点对枚举有效吗?我觉得整个主题有点模糊,我至少还没有发现任何关于这个问题的明确内容,所以我只是仔细检查一下,以免以后再出现问题。

如果还有其他变化我可以添加。

为了快速阅读和误用不同名称的混淆,我想推荐这种形式:

typedef struct Foo {
    int value;
} Foo;

没有对错之分,全凭个人喜好和习惯。

在类似于此的 typedef 声明中

// 1
typedef struct {
    int value;
} Foo;

您不能在结构定义中引用结构。因此,例如,您不能声明表示链表节点的结构,因为在该结构中,您需要引用指向指向下一个节点的结构类型的指针。

在此 typedef 定义中

// 3
typedef struct Foo_s {
    int value;
} Foo_t; 

两个不同的名字Foo_sFoo_t只会让代码的读者感到困惑。比如可以写成

struct Foo_s f = malloc( sizeof( Foo_t ) );

Foo_t f = malloc( sizeof( struct Foo_s ) );

这个 typedef 定义

// 4
typedef struct Foo {
    int value;
} Foo_t;

有同样的问题。例如,如果你会遇到像这样的两个声明

struct Foo f1;

Foo_t f2;

很难说这两种类型是否相同。

所以我更喜欢下面的 typedef 定义

// 2
typedef struct Foo {
    int value;
} Foo;

现在您知道标识符 Foo 是为结构保留的。

这些案例中的大多数都有基于 code-readability/convenience/preference 和限制

等因素的权重
typedef struct {
    int value;
} Foo;

示例 1:一个是正确的,如果出于某种原因您希望使用更方便且更短的 code/code 行,但它的局限性就像您只能像 Foo a; 而不是 [=15] =]

typedef struct Foo {
    int value;
} Foo;

示例 2。与示例 1 类似,但声明限制除外,在示例 2 中您可以像 Foo a;struct Foo a;

一样声明
typedef struct Foo_s {
    int value;
} Foo_t;

示例 3:此示例具有 1 和 2 所没有的 readability/maintainability 因素。如果其他人,甚至将来你自己,将要查看代码,3 肯定会更好地阅读和理解,而不会混淆类型名称。这就是为什么很多地方的标准是这样命名 typedefs/enums/structs 之类的东西。

typedef struct Foo {
    int value;
} Foo_t;

示例 4:4 与 3 相同