4

可能重复:
typedef 类型和相同类型的指针的正确方法是什么?

我最近在我的项目中使用了 Libxml2,并注意到它使用如下 typedef:

typedef struct _xmlNode xmlNode
typedef xmlNode * xmlNodePtr

第一个 typedef 的好处是显而易见的。但是我不确定为什么要为 xmlNode * 分配一个替代名称。对我来说,使用xmlNode *比使用xmlNodePtr更明确和可读,但我可能会遗漏一些东西。

这个 typedef 会解决什么问题,又会带来什么好处呢?

4

4 回答 4

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);
}
于 2012-09-17T21:05:58.510 回答
1

对于某些人来说,名称中带有“ptr”的 typedef 比使用普通指针语法的声明更具可读性和“自然性”。如果你喜欢写作

foo* p;

代替

foo *p;

那么指针 typedef 可能会吸引您,因为它专门避免了写入错误

foo* p, q;

当你的意思是

foo *p, *q;

相反,你可以写

fooptr p, q;
于 2012-09-17T21:05:24.687 回答
1

这个 typedef 会解决什么问题,又会带来什么好处呢?

我的观点是 typedefing 对象指针是不好的,不应该这样做。

首先,它通过隐藏声明的对象是指针类型来改变 C 语言的语法。

第二种类型限定符 ( constand 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 用于结构和指针是错误的。”

于 2012-09-17T21:18:50.260 回答
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

这是一个演示所有这些行为的ideone。

于 2012-09-17T21:23:11.773 回答