之前写一个链表创建的函数,在用typedef对结构体进行取别名的时候,了解到typedef关键字可以为一个结构体取两个别名,于是自己就尝试了一下
///使用typedef定义结构体时可以为其起两个别名
typedef struct List //定义结构体
{
int num;
struct List *next;
}Node,*LinkList; //Node相当于结构体struct List,而LinkList相当于结构体struct List的指针
但是在使用定义了指针的结构体时,如果在函数中想对的结构体进行操作,那就必须要注意你定义的形参到底是结构体本身,还是结构体的指针,还是结构体的指针的指针(二级指针),不同的形参会在函数体中和传入实参时产生差别
下面来看两段代码,注意对比其中的差别:
第一段代码
///一级指针
#include <stdio.h>
#include <malloc.h>
#define LEN sizeof (Node) //定义struct List这个类型的长度
typedef struct List //定义结构体
{
int num;
struct List *next;
}Node,*LinkList;
LinkList create(LinkList head) //创建单链表,注意函数的形参是一个叫head的结构体指针
{
LinkList p1,p2; //p1,p2也是结构体的指针类型
int i,m=10;
head=p1=(LinkList)malloc(LEN); //申请内存,直接使用head(一级指针)
head->next = NULL; //直接使用head
for(i=1;i<m;i++)
{
p2=(LinkList)malloc(LEN); //尾插法建立链表
p2->num=i;
p1->next=p2;
p1=p2;
}
p2->next=NULL;
return head; //使用一级指针时,返回的仍然是链表的指针,在调用时要有一个同类型的指针去接收才能使用链表
}
int main()
{
LinkList L;
int i;
L=create(L); //在调用时要有一个同类型的指针去接收
while(L->next != NULL)
{
L =L->next;
printf("%d",L->num);
}
return 0;
}
第二段代码
///二级指针
#include <stdio.h>
#include <malloc.h>
#define LEN sizeof (Node) //定义struct List这个类型的长度
#define OK 1
#define ERROR 0
typedef struct List //定义结构体
{
int num;
struct List *next;
}Node,*LinkList;
int create(LinkList *head)//(参数为二级指针)LinkList本身就是一个指针类型,而head前面还有一个*,说明head是指针的指针,也就是二级指针
{
LinkList p1,p2; //p1,p2是一级指针
int i,m=10;
*head=p1=(LinkList)malloc(LEN); //申请内存,因为*head相当于一级指针,所以这里使用*head
(*head)->next = NULL; //由于*的运算优先级低于成员操作符->,所以这里要加括号
for(i=1;i<m;i++)
{
p2=(LinkList)malloc(LEN); //尾插法建立链表
p2->num=i;
p1->next=p2;
p1=p2;
}
p2->next=NULL;
return OK;//注意使用二级指针时可以直接在函数中对链表进行操作,不需要返回链表,因此返回值可以是一个状态
}
int main()
{
LinkList L;
int i;
create(&L); //实参传入指针的地址,也就是二级指针,直接在函数中实现了对链表的操作,不再需要用其他指针去接收
while(L->next != NULL)
{
L =L->next;
printf("%d",L->num);
}
return 0;
}
两段代码的主要区别都写在了注释中,总结一下,要是想在函数中直接对链表进行操作(函数用来返回其他的值),则使用二级指针,否则直接返回链表的指针,则形参使用一级指针即可
上面两段示例代码的执行结果就是输出了一个存放数组1-9的链表: