1. 什么是typedef
typedef
是 C 和 C++ 语言中的一个关键字,用于为已有的数据类型定义新的名称(别名)。它的主要作用是增强代码的可读性和可维护性,使得程序员可以更方便地使用复杂数据类型或者简化长类型名的书写。
- 简化复杂类型名称: 使用typedef可以将复杂的类型名简化为一个更简单的别名,提高代码的可读性。
- 跨平台开发: 在跨平台开发中,typedef可以帮助隐藏不同平台下的类型差异,提高代码的可移植性。
- 模块化设计: 有助于将数据类型的定义和使用分离开来,使程序更易于维护和修改。
2. typedef
的用法
2.1 对于数据类型的重定义
使用 typedef
定义类型名后,原类型名作用不变,我们可以通过typedef
对基本数据进行重定义。例如:
typedef int i;
typedef char ch;
typedef long long int lli;
这样我们在后续使用这些数据类型时可以这样写:
i a = 5;
lli b = 10;
ch c = 'a';
// 他们等价于:
int a = 5;
long long int b = 10;
char c = 'a';
2.2 对于函数的重定义
typedef
定义了OperationFunc
类型,它表示一个函数指针,可以指向接受两个整数参数并返回整数的函数。这样,使用OperationFunc
类型来声明函数指针变量op
,可以避免每次声明函数指针时都需要写出完整的指针语法:
#include <stdio.h>
// 定义一个函数指针类型,用 typedef 简化声明
typedef int (*OperationFunc)(int, int);
// 定义两个函数,用于加法和乘法
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) {
return a * b;
}
int main() {
int result;
OperationFunc op; // 使用 typedef 后的函数指针类型
op = add; // 将函数指针指向加法函数
result = op(3, 4); // 调用加法函数
printf("3 + 4 = %d\n", result);
op = multiply; // 将函数指针指向乘法函数
result = op(3, 4); // 调用乘法函数
printf("3 * 4 = %d\n", result);
return 0;
}
输出:
3 + 4 = 7
3 * 4 = 12
注意,typedef
并不用于定义函数本身,而是用于定义类型别名,包括指向函数的指针类型。
因此,你不能使用typedef
来为函数本身提供别名,例如这样是不合法的:
typedef int myFunction(int); // 错误,不能给函数本身起别名
2.3 对于指针的重定义
typedef int* PTRINT;
以上就是给int*
起了一个新的名字PTRINT
。可定义int类型指针变量如:
PTRINT x;
// 等价于:
int* x
示例:
#include<stdio.h>
typedef int* PTRINT;
int main()
{
int a = 0;
PTRINT b = &a;
int* c = &a;
printf("a:%d\na:%p\n", a, &a);
printf("b:%d\nb:%p\n", *b, b);
printf("c:%d\nc:%p\n", *c, c);
return 0;
}
输出:
a:0
a:0000000EB771F794
b:0
b:0000000EB771F794
c:0
c:0000000EB771F794
可以看到b和c无论是值还是地址都是一样的。
2.4 对于数组指针的重定义
#include <stdio.h>
// 假设我们有一个二维整数数组
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 使用 typedef 定义一个二维整数数组指针类型
typedef int (*MatrixPtr)[4];
int main() {
MatrixPtr ptr; // 使用 typedef 后的数组指针类型
ptr = matrix; // 将指针指向二维数组的第一个元素
// 访问数组元素示例
printf("matrix[1][2] = %d\n", ptr[1][2]); // 输出 7
return 0;
}
2.5 对于指针数组的重定义
#include<stdio.h>
typedef int* i[5];
int main()
{
int a = 10, b = 20, c = 30;
i arr = { &a,&b,&c };
printf("%d\n", **arr);
printf("%d\n", **(arr + 1));
printf("%d\n", **(arr + 2));
return 0;
}
输出:
10
20
30
2.6 对于结构体的重定义(typedef struct)
在声明结构体时可为结构体和结构体指针起别名,如:
struct LNode{
ElemType data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode *LinkList;
其表述方式不唯一,也可以写为:
struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
上述两种方式在实际使用过程中:
LNode *next;
// 等价于
LinkList next;
下面我们可以实际使用对比一下:
2.6.1 对结构体起别名
#include <stdio.h>
struct student
{
char name[20];
int age;
char sex[7];
int* score; // 例子:添加一个指向整数的指针成员
};
typedef struct student stu;
int main()
{
int score_value = 85;
struct student a = { "wang", 10, "male", &score_value }; // 初始化包含指针成员的结构体
stu b = { "wang", 10, "male", &score_value }; // 初始化包含指针成员的结构体
printf("struct student的年龄:%d\n", a.age);
printf("struct student的成绩: %d\n", *(a.score)); // 访问指针成员并输出其值
printf("stu的年龄:%d\n", b.age);
printf("stu的成绩: %d\n", *(b.score)); // 访问指针成员并输出其值
return 0;
}
输出:
struct student的年龄: 10
struct student的成绩: 85
stu的年龄: 10
stu的成绩: 85
在这里我们对结构体 struct student
重定义为stu
,并通过 stu
声明变量 a
并进行初始化,可以发现其中struct student
结构体修饰的a
,与typedef
重命名后的stu
所表达的意思是一样的。
2.6.2 对结构体指针起别名
#include <stdio.h>
struct student
{
char name[20];
int age;
char sex[7];
int* score; // 例子:添加一个指向整数的指针成员
};
typedef struct student* pdata;
int main()
{
int score_value = 85;
struct student a = { "wang", 10, "male", &score_value }; // 初始化包含指针成员的结构体
struct student* ptr;
ptr = &a;
//也可以写为 struct student* ptr= &a;
printf("ptr学生姓名:%s\n", ptr->name);
printf("ptr学生年龄:%d\n", ptr->age);
printf("ptr学生性别:%s\n", ptr->sex);
printf("ptr学生成绩:%d\n", *(ptr->score));
pdata pd;
pd = &a;
printf("pd学生姓名:%s\n", pd->name);
printf("pd学生年龄:%d\n", pd->age);
printf("pd学生性别:%s\n", pd->sex);
printf("pd学生成绩:%d\n", *(pd->score));
return 0;
}
输出:
ptr学生姓名:wang
ptr学生年龄:10
ptr学生性别:male
ptr学生成绩:85
pd学生姓名:wang
pd学生年龄:10
pd学生性别:male
pd学生成绩:85