2015-10-17 97 views
2

我是C编程的初学者,我正在研究链接列表。 我想创建一个链接列表,它会按正确的顺序显示这些字母。该程序使用户能够按字母顺序在列表中插入字符或从列表中删除字符。 所以,我以一个例子来说明一点,但有些东西我无法理解。typedef指针在C

这里是代码的第一部分:

#include <stdio.h> 
#include <stdlib.h> 

struct listNode { 
    char data; 
    struct listNode *nextPtr; 
}; 

typedef struct listNode ListNode; 
typedef ListNode *ListNodePtr; 

那部分之后,程序与函数原型开始。 我知道typedef在底部第二行的用法。 但我不知道的是,它包含代码的最后一行:

typedef ListNode *ListNodePtr; 

这是什么意思?

+1

请参阅[对typedef指针是否一个好主意?](http://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers)提供一个强有力的建议最后一行是不利的。至少在你的情况下,它明显包含名称中的'Ptr',但'*'与Ptr'一样清晰。 –

+0

我一直在做什么对于后缀/前缀来说,使用'Ptr'或类似名称的类型名称会更好,而不是将'*'放在typename前面。后者更加明确,并且会更少地污染名称空间,如果您因此而使用它(如果不是这样,那么对于什么来说它会有好处?)。 – Olaf

+0

@Olaf我想我们在几天前有过类似的讨论,有*一个*可能很好用于'typedef'指针,也就是说当客户端代码获取它作为*不透明句柄*并且真的不应该知道它*是一个指针。 (例如,因为它可以在更高的版本中更改为“int”,而不会在API中引入重大更改)当然,这是一个极端情况,当然,您不会**使用“Ptr”后缀... –

回答

6

短版:

typedef ListNode *ListNodePtr; 

ListeNodePtr定义为指针ListNode

您可能想知道为什么星号在这里“坚持”到ListNodePtr。这是因为在C声明中,作为指针被认为是类型修饰符,所以在声明中,它是声明者(变量的标识符或typedef'd类型)的一部分。(*)只要您在一行中有多个声明,例如以下情况:

int *a, b; 

将定义一个指针为inta和一个普通的INTb

你可以把它写成

int* a, b; 

但是这将是非常混乱,因为b仍然是一个指针。

之所以这么说,我个人认为这是风格坏typedef指针,因为作为一个C程序员,你知道星号的含义。将它隐藏在typedef之后(并且如同在这里所做的那样,将其替换为一些非标准后缀,如“Ptr”)只会让代码难以阅读。

(*)在此添加脚注:此设计背后的推理是声明应该看起来与用法相同。*a取消引用一个指针,所以*a还应该声明一个指针。

+1

并添加到你的脚注:当typedef类型是一个结构类型,然后'ListNode * ptr'告诉你使用'ptr-> nextPtr'而不是有效的stilted'( * ptr).nextPtr',或者在一个稍微复杂的表达式中,'ptr-> nextPtr-> data'而不是'(*(* ptr).nextPtr).data'等。当然,你已经检查过在尝试之前'ptr-> nextPtr'不为null。 –

+0

@JonathanLeffler是的,这就是我在这个答案中用我的*观点*之后所做的...明确指出。感谢您为此添加更多推理。 –

2
typedef struct listNode ListNode; 

第一行指ListNode将代表struct listNode

typedef ListNode *ListNodePtr; 

第二行指ListNodePtr将代表ListNode *这是一个指向ListNode

1

A ListNodePtr包含指向ListNode的指针。所以,如果你解开typedef,它就是:struct listNode *