typedef随笔
今天看数据结构的循环单链表的时候发现了一个有意思的问题,先看代码。
InitList(List *CL)
{
*CL = (List)malloc(sizeof(Node));
(*CL)->next = *CL;
}
这里的->一般适用于结构体指针,那么CL为一个指针,可见CL是一个二级指针,而函数形参的声明是List CL,这一般来说是一个一级指针的声明,于是产生了不解,故查看了List结构体的声明如下。
typedef struct Node
{
ElemType data;
struct Node *next;
}Node,*List;
看到这里笔者发现了问题,当时的C语言课程时,老师所教授的typedef的作用和**#define是一样的即是机械替换,那么这里的List*该如何解释?按照笔者习惯将他拆解为:
typedef struct Node* List;
也就是说List其实是一个Node类型的结构体指针声明,可用List代替struct Node*,那么不难看出InitList(List *CL)中的CL其实是一个二级指针的声明。那么这里是为什么用到了二级指针?
答:在InitList函数中,主要是建立循环单链表的头节点,创建好的头节点的next指针必须指向自己,若单单传入一级指针CL将丢失Node结点地址,因为这里的CL只是函数的形参一旦离开函数所保存到的值将丢失。
代码验证
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *next;
} node,*Node;
void func1(Node T){
printf("\nfunc1\n");
printf("T的地址 %p\n",&T);
printf("T的值 %p\n",T);
Node *p;//这里的p是二级指针
p=(Node*)malloc(sizeof(Node));
*p=T;//同为一级指针
printf("p的地址是 %p\n",&p);
printf("p的值是 %p\n",p);
printf("*p的值 %p\n",*p);
}
void func2(Node *T){
printf("\nfunc2\n");
printf("T的地址 %p\n",&T);
printf("T的值 %p\n",T);
printf("*T的值 %p\n",*T);
}
void func3(Node T){
Node p=(Node)malloc(sizeof(node));
T=p;//T指向新节点
printf("新节点的地址 %p\n",p);
}
int main(){
Node T=NULL;
T=(Node)malloc(sizeof(node));
T->data=1;
printf("main函数\n");
printf("T的地址 %p\n",&T);
printf("T的值 %p\n",T);
func1(T);
func2(&T);
func3(T);
printf("在func3中更改T的值后T的值\n %p",T);
}
运行结果:
另注:typedef区别于**#define**的一个点
typedef char *STR;
编译器把STRING解释为一个类型的表示符,该类型指向char。因此
STR name, sign;
等价于
char *name, *sign;
即name和sign均为字符指针,而若用**#define**
#define STR char *
下面的声明:
STR name, sign;
将被翻译成:
char *name, sign;
这导致sign只是一个字符变量。
TR char *
下面的声明:
STR name, sign;
将被翻译成:
char *name, sign;
这导致sign只是一个字符变量。