声明为两种类型的 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_GLContext
是 void*
)。
这里不是这种情况,我同意你的看法,这比帮助更令人困惑。
有些人在命名变量时喜欢遵循 Hungarian Notation 的想法。有些人在命名类型时会进一步使用该概念。
我认为这是一个品味问题。
但是,我认为它掩盖了一些事情(就像在你的例子中一样),因为你必须挖掘 name 的 declaration ] 为了找到它的类型。我更喜欢显而易见和明确的事情,我会避免这样的类型名称。
(请记住,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
,但这是这样做的原因。
抱歉,如果之前有人问过这个问题,我什至不确定要搜索什么才能提出这个问题。
当我创建一个 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_GLContext
是 void*
)。
这里不是这种情况,我同意你的看法,这比帮助更令人困惑。
有些人在命名变量时喜欢遵循 Hungarian Notation 的想法。有些人在命名类型时会进一步使用该概念。
我认为这是一个品味问题。
但是,我认为它掩盖了一些事情(就像在你的例子中一样),因为你必须挖掘 name 的 declaration ] 为了找到它的类型。我更喜欢显而易见和明确的事情,我会避免这样的类型名称。
(请记住,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
,但这是这样做的原因。