typedef的指针类型被认为是不好的做法吗?

Bla*_*iev 15 c pointers typedef

可能重复:
Typedef指针是个好主意?

我在许多使用过的API中都看到了这种奇怪之处:

typedef type_t *TYPE;
Run Code Online (Sandbox Code Playgroud)

我的观点是声明一个类型的变量TYPE将不会清楚地表明事实上已经声明了一个指针.

你和我一样认为这会带来很多困惑吗?这是否意味着强制执行封装,还是有其他原因?你认为这是一种不好的做法吗?

Joh*_*all 24

一般来说,这是一种不好的做法.重要的问题是它不能很好地与const:

typedef type_t *TYPE;
extern void set_type(TYPE t);

void foo(const TYPE mytype) {
  set_type(mytype);  // Error expected, but in fact compiles
}
Run Code Online (Sandbox Code Playgroud)

为了使作者foo()能够表达他们真正的意思,提供的图书馆还TYPE必须提供CONST_TYPE:

typedef const type_t *CONST_TYPE;
Run Code Online (Sandbox Code Playgroud)

所以foo()可以有签名void foo(CONST_TYPE mytype),此时我们已经陷入了闹剧.

因此经验法则:

创建结构的typedef(特别是不完整的结构),而不是指向那些结构的指针.

如果底层结构的定义不是公开可用的(这通常是值得称赞的),那么该封装应该由结构提供不完整,而不是由不方便的typedef提供:

struct type_t;
typedef struct type_t type_t;

void set_type(type_t *);
int get_type_field(const type_t *);
Run Code Online (Sandbox Code Playgroud)


cob*_*bal 6

一个常见的习语是用类型后缀_p来表示它是一个指针,同时仍保留指针质量.

有时,如果指向的结构不可公开,则只需使用指针类型.这有助于促进数据隐藏.即

typedef struct hidden_secret_object * object;
void change_object(object foo);
Run Code Online (Sandbox Code Playgroud)

这允许您在hidden_secret_object不破坏外部代码的情况下更改结构化方式.

  • 为什么你需要typedef中的指针来隐藏数据?`typedef struct h_s_o object; void change_object(object*foo);`会完成同样的事情.该示例与该问题无关. (2认同)

Tac*_*lff 5

我也不清楚.我也不喜欢完全大写的类型(我试着为#defines保留那些).

这种方式通过认为它实际上是一种值类型而很容易自欺欺人,而我们正在讨论指针类型.可以使用智能指针完全抽象出指针类型,但这在C语言中并不常见.

后缀(如前所述)_p,_ptr,Pointer或沿着这些线的任何东西都会产生清晰度; 增加打字,这是真的,但会阻止你犯愚蠢的错误(例如使用'.'而不是' - >',......)会花费你宝贵的开发时间.


AnT*_*AnT 5

这取决于你想要达到的目标.对于您提出的问题,您的问题没有任何有意义的"是或否"答案.

  • 如果你试图创建一个抽象句柄类型,暗示用户不应该知道或关心隐藏在类型后面的东西,那么键入定义指针类型就完全没问题了.重点是,今天它可能是一个指针类型,明天它可能会成为一个整数类型,后来它可能会变成其他东西.这正是指针类型typedef在大多数库接口中通常使用的内容.

你说有时它"不清楚是否声明了指针".但在这种使用模式下,这正是重点!它应该是"不清楚".事实上,该类型恰好是一个混淆的指针,这不关你的事.这是你不需要知道而不应该依赖的东西.

此使用模型的典型示例是va_list标准库中的类型.在某些实现中,它可能很容易成为指针类型的typedef.但那是你不应该知道或依赖的东西.

另一个例子是HWNDWindows API中的类型定义.它也是指针类型的typedef,但这不关你的事.

  • 一种完全不同的情况是当你将指针类型作为速记形式输入时,只需要使声明更短,而不必*每次都输入字符.在这种情况下,typedef(并且将始终是)代表指针类型的事实向用户公开.通常这种用法不是一种好的编程习惯.如果用户想要创建别名以避免*每次都键入,他们可以自己完成.

由于您在OP中已经提到过的原因,此使用模型通常会导致代码更加模糊.

在Windows API中也可以找到这种错误使用typedef的示例.Typedef名称PINT完全遵循有缺陷的使用模型.