《小菜狗 C 语言入门 + 进阶笔记》(36)typedef 关键字【在比较大的工程内很常用!】


《小菜狗 C 语言入门 + 进阶笔记》目录:《小菜狗 C 语言入门 + 进阶笔记》(0)简介

1、typedef 关键字

1.1、引入

C 语言允许为一个数据类型起一个新的别名,就像给人起 “绰号” 一样。

C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。

起别名的目的不是为了提高程序运行效率,而是为了编码方便。

typedef 的用法一般为:

typedef  oldName  newName;
1.2、为变量取别名

⽐如,你觉得 unsigned char 写起来不⽅便,如果能写成 uchar 就⽅便多了,如下:

typedef unsigned char c;

在这个类型定义之后,标识符 uchar 可作为类型 unsigned char 的缩写,例如:

原来写法:
unsigned char b1, b2;
缩写:
uchar b1, b2;
1.3、为数组取别名
typedef int A[6];

详细解释:

  • 表示用 A 代替 int [6]。即:A a; == int a[6];
  • A 是类型 int [6] 的别名;
  • 它是一个长度为 6 的数组类型。

接着可以用 A 定义数组

A a1, a2;

它等价于:

char a1[6], a2[6];

注意:数组也是有类型的。例如 char a1[20]; 定义了一个数组 a1,它的类型就是 char [20]

1.4、为结构体取别名

先对结构体使用 typedef 来定义一个新的数据类型名字,然后使用这个新的数据类型来直接定义结构变量,如下:

#include <stdio.h>
#include <string.h>
 
typedef struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} Book;
 
int main( )
{
   Book book;
 
   strcpy( book.title, "C 教程");
   strcpy( book.author, "BOBO"); 
   strcpy( book.subject, "编程语言");
   book.book_id = 12345;
 
   printf( "书标题 : %s\n", book.title);
   printf( "书作者 : %s\n", book.author);
   printf( "书类目 : %s\n", book.subject);
   printf( "书 ID : %d\n", book.book_id);
 
   return 0;
}

运行结果:

书标题 : C 教程
书作者 : BOBO
书类目 : 编程语言
书 ID : 12345

Book 是 struct Books 的别名,可以用 Book 定义结构体变量

Book body1,body2;

它等价于:

struct Books body1, body2;
1.5、为指针取别名

指针类型也是可以的,如下将 int* 重命名为 ptr_t

typedef int* ptr_t; 

typedef 还有一个作用: 为复杂的声明定义一个新的简单的别名。

用在回调函数中特别好用!

1.6、为数组指针取别名

原声明:

int *(*a[5])(int, char*);

在这里,变量名为 a,直接用一个新别名 pFun 替换 a 就可以了:

typedef int (pFun)(int, char*);

于是,原声明的最简化版:

pFun a[5];
1.7、为函数指针取别名

原声明:

void (*b[10]) (void (*)());

这里,变量名为 b,先替换右边部分括号里的,pFunParam 为别名一:

typedef void (*pFunParam)();

再替换左边的变量 bpFunx 为别名二:

typedef void (*pFunx)(pFunParam);

于是,原声明的最简化版:

pFunx b[10];

其实,可以这样理解:

typedef int (pFun)(int, char*); 

typedef 定义的函数 pFun,为一个新的类型,所以这个新的类型可以像 int 一样定义变量,于是,pFun a[5]; 就定义了 int \*(\*a[5])(int, char\*);

所以我们可以用来定义回调函数,特别好用。

另外,也要注意,typedef 在语法上是一个存储类的关键字(如 auto、extern、mutable、static、register 等一样),虽然它并不真正影响对象的存储特性,如:

typedef static int INT2; // 不可行

编译将失败,会提示“指定了一个以上的存储类”。

2、typedef 与 #define

#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似。

typedef 与 #define 相同之处:

  • typedef 和 define 都可以替一个对象取一个别名,以此增强程序的可读性。

但是它们有以下几点不同:

  • #define 常用于定义常量或替换文本,typedef常用于定义类型别名。
  • typedef 给出的符号名称仅限于对类型定义别名,而 #define 不仅可以对类型定义别名,也能为数值定义别名。
  • typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。

简而言之,#define 只是字面上的替换,由预处理器执行,#define A B 相当于打开编辑器的替换功能,把所有的 B 替换成 A。

使用上的区别:

(1)#define 可以使用其他类型说明符对宏类型名进行扩展,但对 typedef 所定义的类型名却不能这样做。

如下:

#define INTERGE int;
unsigned INTERGE n;  //没问题
typedef int INTERGE;
unsigned INTERGE n;  //错误,不能在 INTERGE 前面添加 unsigned

(2) 在连续定义几个变量的时候,typedef 能够保证定义的所有变量均为同一类型,而 #define 则无法保证

如下:

#define PTR_INT int *
PTR_INT p1, p2;

p1、p2 类型不相同,宏展开后变为 int *p1, p2。

typedef int * PTR_INT
PTR_INT p1, p2;

p1、p2 类型相同,它们都是指向 int 类型的指针。

每日一更!

公众号、优快云等博客:小菜狗编程笔记

谢谢点赞关注哈!目前在飞书持续优化更新~

日更较慢有需要完整笔记请私我,C/C++/数据结构-算法/单片机51-STM32-GD32-ESP32/嵌入式/Linux操作系统/uboot/Linux内核-驱动-应用/硬件入门-PCB-layout/Python/后期小程序和机器学习!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鹅编程笔记

你的鼓励将是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值