声明为两种类型的 Typedef 结构:"typedef struct x { .. } X, *XPointer"

Typedef struct declared as two types: "typedef struct x { .. } X, *XPointer"

抱歉,如果之前有人问过这个问题,我什至不确定要搜索什么才能提出这个问题。

当我创建一个 typedef struct 时,我通常会这样做:

typedef struct myStruct {
  int a;
  int b;
  struct myStruct *next;
} MyStruct;

所以我在最后用MyStruct声明它。然后当我创建将其作为参数传递的函数时,我写

int doSomething(MyStruct *ptr){

}

然而我正在和一个朋友合作一个项目,我遇到了他的编码风格,就是 像这样声明 *MyStructP:

typedef struct myStruct {
  int a;
  int b;
  struct myStruct *next;
} MyStructR, *MyStructP;

然后他在他的函数中使用了MyStructP,所以他的参数看起来像:

int doSomething(MyStructP)

所以他不必使用参数列表中的*。这让我感到困惑,因为当我查看参数列表时,我总是寻找 * 来确定 arg 是否为指针。最重要的是,我正在创建一个函数,该函数接受我创建的结构和他创建的结构,因此我的 arg 有 * 而他没有。超级混乱!!

有人可以 insight/comparison/advice 说明两者之间的区别吗?优点?缺点?哪种方式更好或更差,或更广泛使用?任何信息。谢谢!

将指针隐藏在 typedef 后面通常被认为是糟糕的风格,除非它们是不透明的句柄(例如 SDL_GLContextvoid*)。
这里不是这种情况,我同意你的看法,这比帮助更令人困惑。

有些人在命名变量时喜欢遵循 ​​Hungarian Notation 的想法。有些人在命名类型时会进一步使用该概念。

我认为这是一个品味问题。

但是,我认为它掩盖了一些事情(就像在你的例子中一样),因为你必须挖掘 namedeclaration ] 为了找到它的类型。我更喜欢显而易见和明确的事情,我会避免这样的类型名称。

(请记住,typedef 不会引入新类型,而只是引入新类型的别名。)

Linux kernel coding style 说要避免这些类型定义:

Chapter 5: Typedefs

Please don't use things like "vps_t".

It's a mistake to use typedef for structures and pointers. When you see a

vps_t a;

in the source, what does it mean?

In contrast, if it says

struct virtual_container *a;

you can actually tell what "a" is.

人们偶尔使用 typedef 指针的主要原因是向程序员将类型表示为 "black box object",并允许将来更轻松地更改其实现。

例如,也许今天该类型是一个指向结构的指针,但明天该类型将成为某些 table、某种 handle/key 或文件描述符的索引。 Typedef'ing 这种方式告诉程序员他们不应该尝试他们通常可能对指针做的事情,例如将它与 0 / NULL 进行比较,取消引用它(例如 - 直接访问成员),递增它等等,作为他们的代码将来可能会坏掉。当然,使用命名约定(例如您的朋友所做的)来揭示和编码底层实现实际上是一个与该目的冲突的指针。

这样做的另一个原因是为了减少这种错误的可能性:

myStructR *ptr1, ptr2;
myStructP  ptr3, ptr4;

这是一个非常弱的调味料,因为编译器通常会在以后发现您滥用 ptr2,但这是这样做的原因。