在C语言中,我们经常会遇到定义结构体、联合体、枚举和函数指针等等这些复杂的类型,这些类型的定义不仅晦涩难懂,而且会导致代码重复和不易维护。C语言提供了typedef关键字,它可以让我们为定义的类型取一个别名,从而简化代码的复杂度,并且让程序更加优雅。
一、typedef与声明的关系
在介绍typedef之前,先来看一下声明与定义的关系。声明通常是指我们需要告诉编译器将一个标识符解释为一个特定的类型。我们可以在程序中这样声明一个变量:
```c
int i;
```
这个声明告诉编译器我们要使用一个名为i的整型变量,但是并没有对这个变量进行赋值。实际上,这个变量的内存空间也还没有确定分配。
定义则是指我们为某个声明分配了物理内存空间。如果我们需要将i定义为10,可以这样写:
```c
int i = 10;
```
这个定义告诉编译器,为i分配了一个int类型的内存空间,并且将10赋值给了这个内存空间中的值。
typedef可以为一个类型重新定义一个别名,并且在程序中使用这个别名。
例如,我们可以像这样定义一个复杂的类型:
```c
struct employee
{
char name[20];
int age;
double salary;
};
```
这个定义使用了C语言的结构体定义方式,定义了一个包含名字、年龄和薪水信息的employee结构体类型。如果我们需要在程序中定义一个这样的结构体变量,可以这样写:
```c
struct employee emp;
```
然而,每次我们需要定义这个结构体变量的时候,都需要写出这个冗长的struct employee,这样不仅比较麻烦,而且不符合程序简洁的要求。
这时候,typedef就可以派上用场了。我们可以使用typedef来重新定义一个新的别名:
```c
typedef struct employee
{
char name[20];
int age;
double salary;
} EMPLOYEE;
```
这个代码定义了一个别名EMPLOYEE,这个别名意味着我们可以使用EMPLOYEE来代替struct employee,这样写程序将变得更加简洁。
例如,我们可以这样定义一个EMPLOYEE类型的变量:
```c
EMPLOYEE emp;
```
二、使用typedef定义函数指针类型
typedef不仅可以为一个复杂的类型定义别名,还可以为一个函数指针类型定义别名。在C语言中,函数指针是一种特殊的指针,它指向了程序中的一个函数。
例如,我们可以声明一个函数指针类型,并且定义一个函数:
```c
int (*pFunc)(int,int);
int add(int a, int b)
{
return a + b;
}
```
这个代码定义了一个名字为pFunc、参数类型为两个int型变量、返回值为int型的函数指针类型,并且定义了一个add函数,这个函数用于实现求和操作。
现在我们需要使用这个函数指针类型来调用add函数,可以使用如下代码:
```c
pFunc = add;
int result = pFunc(2, 3);
```
这个代码将add函数地址赋值给pFunc,并且通过pFunc调用add函数,将函数的返回值赋值给result。
以上代码有些晦涩难懂,我们可以使用typedef来为函数指针类型取一个别名,让代码变得更加容易理解。
```c
typedef int (*P_FUNC)(int,int);
P_FUNC pFunc = add;
int result = pFunc(2, 3);
```
这个代码用P_FUNC代替了晦涩的函数指针类型定义,让代码变得清晰易懂。
三、使用typedef定义枚举类型
在C语言中,枚举类型是一种特殊的数据类型,它定义了若干个标识符,这些标识符的值依次为0、1、2……。这个数据类型经常用于程序中定义一些常量和状态值。
例如,我们可以定义一个枚举类型,用于表示一周中的天数:
```c
enum WEEK
{
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
Sun
};
```
这个代码定义了一个WEEK枚举类型,并且定义了七个标识符,分别表示一周中的七天,它们的值分别为0、1、2……。
现在我们需要在程序中使用这个枚举类型,可以这样定义一个变量:
```c
enum WEEK day = Mon;
```
这个代码定义了一个名为day的WEEK类型的枚举变量,并把它赋值为星期一。
如果你认为声明WEEK类型有点繁琐,不妨使用一个别名来简化代码。
```c
typedef enum WEEK
{
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
Sun
} DAY;
DAY day = Mon;
```
这个代码使用typedef为WEEK类型定义了别名DAY,并且使用DAY代替了WEEK,让代码变得更加简洁。
四、使用typedef定义联合体类型
在C语言中,联合体是一种特殊的数据类型,它可以存储不同的数据类型,并且它所有的成员变量使用同一块内存空间。这个特性使得使用联合体有时会比使用结构体更加灵活。
例如,我们可以这样定义一个联合体类型:
```c
union VALUE
{
int i;
double d;
char c;
};
```
这个代码定义了一个联合体类型VALUE,这个类型包含了三个不同类型的成员变量:整型i、双精度浮点数d和字符c。所有这些变量都使用了同一块内存空间,即联合体的大小等于其中最大的成员变量占用的字节数。
现在,我们需要在程序中使用这个联合体类型,可以这样定义一个变量:
```c
union VALUE val;
```
这个代码定义了一个名为val的联合体变量。实际上,我们也可以为这个联合体类型定义一个别名,让程序变得更加简洁:
```c
typedef union VALUE
{
int i;
double d;
char c;
} VALUE_TYPE;
VALUE_TYPE val;
```
这个代码使用typedef定义了一个别名VALUE_TYPE,并通过VALUE_TYPE代替了联合体的类型名称VALUE。这样,我们就可以使用VALUE_TYPE来定义联合体类型的变量,让程序变得更加易读易懂。
五、使用typedef定义复杂的类型
在许多情况下,我们需要定义的数据类型可能比较复杂,例如,一个包含多个成员变量的结构体,或者一个包含多个指针的函数指针类型。这些类型的定义一般比较长,难以理解。
如果你想定义一个复杂类型并且它的名称经常出现在程序中,那么你可以使用typedef为它定义一个别名,以便于代码的维护和阅读。
例如,我们可以定义一个复杂的结构体类型:
```c
struct article
{
char title[50];
char author[30];
char content[1000];
int hit_count;
struct tm publish_time;
char* comments[20];
int comment_count;
};
struct article news;
```
这个代码定义了一个结构体类型article,并定义了一个news结构体变量。这个结构体类型包含很多成员变量,如果在程序中经常使用,将会影响代码的可读性。
因此,我们可以使用typedef为这个结构体类型定义一个别名ARTICLE,并使用ARTICLE来代替struct article:
```c
typedef struct article
{
char title[50];
char author[30];
char content[1000];
int hit_count;
struct tm publish_time;
char* comments[20];
int comment_count;
} ARTICLE;
ARTICLE news;
```
这样,我们就可以使用ARTICLE来定义这个结构体类型的变量,让程序的可读性得到了大幅提高。
六、总结
在C语言中,typedef可以为一个复杂的类型定义一个简单易懂的别名,从而使程序变得更加优雅。typedef的用法不仅可以用来为结构体、联合体、枚举和函数指针类型定义别名,也可以用来为复杂的数据类型定义别名。使用typedef之后,程序的可读性和可维护性都将得到显著的提高。我们可以在代码中充分使用typedef,以取得更好的代码风格。