在C中,使用typedef指针是一种好的形式吗?

时间:2013-06-16 15:51:15

标签: c pointers typedef

考虑以下C代码:

typedef char * MYCHAR;
MYCHAR x;

我的理解是结果是x是“char”类型的指针。但是,如果x的声明远离typedef命令发生,则代码的人类读者不会立即知道x是指针。或者,可以使用

typedef char MYCHAR;
MYCHAR *x;

哪种形式被认为更好?这不仅仅是风格问题吗?

8 个答案:

答案 0 :(得分:7)

如果指针永远不会被解除引用或直接操作 - IOW,你只将它作为参数传递给API - 那么可以将指针隐藏在typedef后面。

否则,最好使类型的“指针”显式化。

答案 1 :(得分:3)

我并不特别喜欢指针的typedef,但它有一个优点。当您在单个声明中声明多个指针变量时,它可以消除混淆和常见错误。

typedef char *PSTR;
...
PSTR str1, str2, str3;

可以说比以下更清楚:

char *str1, str2, str3;  // oops

答案 2 :(得分:2)

我更喜欢离开*,它显示有一个指针。你的第二个例子应缩短为char* x;,这没有任何意义。

答案 3 :(得分:2)

我也认为这是风格/惯例的问题。在Apple的Core Graphics库中,他们经常“隐藏”指针并使用将“Ref”附加到类型末尾的约定。例如,CGImage *对应CGImageRef。这样你仍然知道它是一个指针引用。

答案 4 :(得分:2)

我只会在结果类型的指针性质没有意义的情况下使用指针typedef。例如,当想要声明一个不透明的“句柄”类型时,指针typedef是合理的,它恰好被实现为一个指针,但不应该被用户用作指针。

typedef struct HashTableImpl *HashTable;
/* 'struct HashTableImpl' is (or is supposed to be) an opaque type */

在上面的示例中,HashTable是哈希表的“句柄”。用户最初会从CreateHashTable函数接收该句柄,并将其传递给HashInsert函数等。用户不应该关心(甚至不知道)HashTable是指针。

但是在用户应该理解该类型实际上是指针并且可用作指针的情况下,指针typedef会使代码混淆不清。我会避免他们。明确声明指针使代码更具可读性。

值得注意的是,C标准库避免了这种指针类型的定义。例如,FILE显然是用作opaque类型,这意味着库可以将其定义为typedef FILE <some pointer type>,而不是让我们一直使用FILE *。但出于某种原因,他们决定不这样做。

答案 5 :(得分:0)

另一种看待它的方法是从类型的角度来看。类型定义该类型可能的操作,以及调用这些操作的语法。从这个角度来看,MYCHAR就是它的全部。程序员有责任了解允许的操作。如果它被声明为第一个示例,则它支持*运算符。您始终可以恰当地命名标识符以阐明其使用。

声明作为指针的类型有用的其他情况是当参数的性质对用户(程序员)不透明时。可能有API想要返回指向用户的指针,并期望用户在其他某点将其传递回API。像不透明的句柄或cookie一样,API仅在内部使用。用户不关心参数的性质。通过在API中暴露*来使水混淆或暴露其确切性质是有道理的。

答案 6 :(得分:0)

如果您查看几个现有的API,看起来好像没有将指针放入类型似乎更好的样式:

可能还有很多其他人。

答案 7 :(得分:0)

对于API,隐藏“抽象”typedef背后的结构定义和指针是

        /* This is part of the (hypothetical) WDBC- API
        ** It could be found in wdbc_api.h
        ** The struct connection and struct statement ar both incomplete types,
        ** but we are allowed to use pointers to incomplete types, as long as we don't
        ** dereference them.
         */
struct connection *wdbc_connect (char *connection_string);
int wdbc_disconnect (struct connection *con);
int wdbc_prepare (struct connection * con, char *statement);

int main(void)
{
  struct connection *conn;
  struct statement *stmt;
  int rc;

  conn = wdbc_connect( "host='localhost' database='pisbak' username='wild' password='plasser'" );
  stmt = wdbc_prepare (conn, "Select id FROM users where name='wild'" );

  rc = wdbc_disconnect (conn);

  return 0;
}

上面的片段编译得很好。 (但显然无法链接)