考虑以下C代码:
typedef char * MYCHAR;
MYCHAR x;
我的理解是结果是x是“char”类型的指针。但是,如果x的声明远离typedef命令发生,则代码的人类读者不会立即知道x是指针。或者,可以使用
typedef char MYCHAR;
MYCHAR *x;
哪种形式被认为更好?这不仅仅是风格问题吗?
答案 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,看起来好像没有将指针放入类型似乎更好的样式:
FILE *
mysql_real_connect()
MYSQL *
mysql_store_result()
和mysql_use_result()
MYSQL *
可能还有很多其他人。
答案 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;
}
上面的片段编译得很好。 (但显然无法链接)