ANSI C - 使用typedef为指针类型指定备用名称的好处

时间:2012-09-17 20:58:43

标签: c

  

可能重复:
  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 更明确和可读,但我可能会遗漏一些东西。

这种类型的解决方案会遇到什么问题?它会带来什么好处?

4 个答案:

答案 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语言的语法。

第二个类型限定符(constvolatile)无法穿透typedef。

如果我们举个例子:

typedef struct _xmlNode xmlNode;
typedef xmlNode * xmlNodePtr;

现在无法使用const别名声明对象,因此指针对象为xmlNodePtr

const xmlNodePtr xp;

表示xpconst而不是*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

Here's an ideone demonstrating all of this behavior.