typedef声明
1、前言
C语言中的typedef是一个关键字,提供了一种声明标识符为类型别名的方式,能用来替换复杂的类型名,如果一个声明以typedef为存储类指定符,则其中每个声明符都会定义一个标识符为指定类型的别名,typedef声明不能为static或者extern,它不引入另一种类型,只会建立已经存在类型的同义词。
2、常见用法
使用typedef为现有的类型创建别名,定义容易记忆的类型名:
typedef int size; /* size别名 */ void fun(size *p); /* 形参中使用size别名 */ size len = file.getlength(); /* 定义变量并赋值 */
使用typedef去掩饰一些复合数据类型,例如指针和数组:
比如说,可以不用像下面这样重复定义具有20个元素的字符数组:
char a[20]; /* 定义20个元素的字符数组 */ char b[20];
使用typedef,String类型就代表了具有20个元素的字符数组,如下:
typedef char String[20]; String str1,str2; /* 定义str1和str2变量,为20个元素的字符数组 */
例如:可以使用下面的例子进行字符串打印:
#include <stdio.h> #include <string.h> typedef char String[20]; int main(int argc, char *argv[]) { String str1; memcpy(str1, "Hello World.", strlen("Hello World.")); printf("str1 = %s\n", str1); return 0; }
另外,还可以如下代码一样,隐藏指针语法:
typedef char* pstr; void fun(pstr str1, pstr str2);
typedef声明可以是不完整的类型,它会照样变得完整,如下:
typedef int Num[]; /* Num是int[]类型 */ Num n = {1, 2, 3}; /* n的类型是int[3] */ Num m = {1, 2, 3, 4}; /* m的类型是int[4] */
例如:使用下面的代码打印整型数组n和m:
#include <stdio.h> typedef int Num[]; int main(int argc, char *argv[]) { Num n = {1, 2, 3}; Num m = {1, 2, 3, 4}; int i; for(i = 0; i < 3; i++) printf("n[%d] = %d\n", i, n[i]); for(i = 0; i < 4; i++) printf("m[%d] = %d\n", i, m[i]); return 0; }
typedef声明还能配合struct结构体使用:
typedef struct pNode pNode; struct pNode { int num; pNode *pNext; /* 同struct pNode *pNext; */ }; /* pNode是一个完整的类型 */ pNode Node, *p; /* 同struct pNode Node, *p; */
例如:使用下面的代码定义结构体节点,并输出其节点标号:
#include <stdio.h> typedef struct pNode pNode; struct pNode { int num; pNode *pNext; }; int main(int argc, char *argv[]) { pNode first,second; /* 定义两个节点 */ first.num = 1; first.pNext = &second; second.num = 2; second.pNext = NULL; printf("first.num = %d\n", first.num); printf("second.num = %d\n", (first.pNext)->num); return 0; }
typedef声明还可以用来简化复杂声明的语法:
/* 5个函数指针的数组,函数返回指向3个int的数组的指针 */ int (*(*callbacks[5])(void))[3] /* 使用typedef简化 */ typedef int arr_t[3]; /* arr_t是3个int的数组 */ typedef arr_t* (*fp)(void); /* 指针指向的函数返回类型为arr_t* */ fp callbacks[5]; /* 5个函数指针的数组 */
3、typedef与#define的问题
#define可以理解为直接替换,一般在带有表达式的宏定义中,表达式必须要使用括号,通常来讲,typedef要比#define要好,特别是在指针的场合,如下例子:
typedef char* pStr1; /* 使用typedef声明 */ #define pStr2 char* /* 使用宏定义 */ /* 相关变量定义 */ pStr1 string1, string2; pStr2 string3, string4;
在代码的变量定义中,string1、string2以及string3都将被定义为char*类型,但是string4则被定义成了char类型,而并没有到达所预期的字符指针变量的效果,对于#define只是简单的字符串替换而typedef则是为一个类型起新的别名,在上面的代码中,如果string3和string4都要被定义为char*类型的话,需要像下面进行定义:
typedef char* pStr1; /* 使用typedef声明 */ #define pStr2 char* /* 使用宏定义 */ /* 相关变量定义 */ pStr1 string1, string2; pStr2 string3, *string4;
4、小结
对于typedef的常见用法就介绍到这,在编程中使用typedef的目的一般有2个,一个就是给已经存在的数据类型定义一个容易记忆并且意义明确的别名,另外一个就是去简化一些比较复杂的声明。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App