可能重复:
What is the right way to typedef a type and the same type's pointer?
我最近在我的项目中使用了Libxml2,发现它使用了类似以下的typedef:
typedef struct _xmlNode xmlNode
typedef xmlNode * xmlNodePtr
第一种类型的优点显而易见。但是我不确定为什么要为xmlNode *指定一个替代名称。对我来说,使用 xmlNode * 比使用 xmlNodePtr 更明确和可读,但我可能会遗漏一些东西。
这种类型的解决方案会遇到什么问题?它会带来什么好处?
答案 0 :(得分:2)
C API通常会提供不透明句柄,这会阻止消费者询问他们是什么并试图在里面戳。这些手柄是指针的事实并不重要,对消费者来说无关紧要,也不应该为额外的明星的词汇杂乱负担。
例如,通过定义句柄来编写C ++绑定是完全可能的:
typedef void * MyHandle;
现在我们给幸福的C消费者一些功能:
MyHandle create_gizmo();
void destroy_gizmo(MyHandle);
int do_magic(MyHandle, int, int);
这很简单。用户立即看到如何使用它:
#include "MagicAPI.h"
MyHandle h = create_gizmo();
submit_result(do_magic(h, 12, 91));
destroy_gizmo(h);
C ++库开发人员只需解开句柄并填充API函数(当然声明为extern "C"
):
#include "MagicAPI.h"
#include "SuperGizmo.hpp"
MyHandle create_gizmo() { return static_cast<MyHandle>(new SuperGizmo); }
void destroy_gizmo(MyHandle h) { delete static_cast<SuperGizmo *>(h); }
int do_magic(MyHandle h, int a, int b)
{
return static_cast<SuperGizmo *>(h)->foo(a, b);
}
答案 1 :(得分:1)
对于某些人,使用&#34; ptr&#34;在名称中更具可读性和自然性#34;比使用普通指针语法的声明。如果你喜欢写作
foo* p;
而不是
foo *p;
然后指针typedef可能会吸引你,因为它特别避免了编写错误
foo* p, q;
当你意味着
foo *p, *q;
相反,你可以写
fooptr p, q;
答案 2 :(得分:1)
这种类型的解决方案会遇到什么问题?它会带来什么好处?
我认为typedefing对象指针很糟糕,不应该这样做。
首先,它通过隐藏声明的对象是指针类型来改变C语言的语法。
第二个类型限定符(const
和volatile
)无法穿透typedef。
如果我们举个例子:
typedef struct _xmlNode xmlNode;
typedef xmlNode * xmlNodePtr;
现在无法使用const
别名声明对象,因此指针对象为xmlNodePtr
。
const xmlNodePtr xp;
表示xp
为const
而不是*xp
。
const xmlNode x = /* ... */;
const xmlNodePtr xp = &x; // Error!
顺便说一下,在Linux内核编码风格中,他们还建议不要使用typedef
作为指针:
“对于结构和指针使用typedef是错误。”
答案 3 :(得分:0)
存在一些差异。
首先,如果您在一行中执行多个声明,则以下两个片段是等效的:
char *c1, *c2, *c3, *c4;
typedef char * charPtr;
charPtr c1, c2, c3, c4; // I don't need to repeat the unary * everywhere
这很有用,因为您可能会遇到类似以下内容的问题:
char * c1, c2, c3, c4; // declares one char pointer and three chars
其次,它们可以大大简化函数指针类型的定义,这几乎是无限丑陋和肮脏的机会。
float (*someCrazyFunction)(float(*)(), float) = foo; // WTF is this
typedef float (*crazyFunction)(float(*)(), float);
crazyFunction myCrazyFunction = foo; // easier to deal with