当前位置: 首页 > article >正文

C——Typedef是什么?如何使用?有何便利之处?

Typedef 是什么?

typedef是 C 语言中的一个特色功能,被用于创建新的类型名称,从名称“type def(ine)”也可以看出其功能。typedef类似于 Unix 中的alias程序的功能,为一个对象添加另外一个名称,typedef使得多个名称其实对应的是同一个程序,但是typedef操作的对象是数据类型,也就是给数据类型“起外号”,这个外号一般首字母大写,用于表示不是基础数据类型

在 C 语言中,typedef与宏#define很相似,二者的区别放到最后,因为需要先理解typedef,才能理解其与宏的区别。

Typedef 如何使用?

比如说,在 C 语言中,是有字符串的概念的:char类型的数组,最后一个元素为\0表示字符串结束。并且元素类型为char的数组其实等价于指向char的指针。但是 C 语言中并没有String这种数据类型。那么就可以使用以下语句来实现同等的功能:

//String是一个指针,*String(就是该指针的内容)等于char。换句话说,String 等于 char *
typedef char *String

从这里也可以看出来,这个外号并不是在typedef后面,而是在数据类型后面的变量的位置。(C 语言中,声明、定义变量的时候,变量是不是在类型后面?)

这时候便可以使用以下语句声明、赋值、输出“字符串”类型的数据。如下 :

#include <stdio.h>

int main()
{
    typedef char *String;
    
    String p = "abc";
    printf("%s\n", p);
    return 0;
}

输出为:

abc

再次强调,typedef并没有创建新的数据类型,只是起了个“外号”,这里的字符串也是利用 C 语言本身的机制实现的。

当然这种方法不是很常见,大多数情况不会给基础数据类型“起外号”,毕竟大部分基础数据类型的名称已经很简洁、易懂了,字符串是个例外。最常见的是在使用结构体自定义数据类型的时候,使用typedef来找一个简单些或者更易懂的同义词,而且还能让代码更简洁、高效。

比如下面这段代码,是很经典的二叉树节点的结构体:

struct tnode {
    char *word;
    int count; 
    struct tnode *left; 
    struct tnode *right; 
};

新建一个新的节点,并为其分配空间的方法如下:

struct tnode *talloc(void)
{
    return (struct tnode *) malloc(sizeof(struct tnode));
}

如果使用typedef的方法,也就是在声明结构体tnode的同时,用typedef给它起一个“外号”Treenode,如下:

typedef struct tnode {
	char *word;
	int count;
	Treeptr left;
	Treeptr right;
} Treenode;

然后再使用typedef定义一个“外号”*Treeptr

typedef struct tnode *Treeptr;

这样的话,新建并分配内存的方法不仅简洁了,而且可以写成没有指针符号*的样式,如下:

Treenode talloc(void)
{
    return (Treeptr) malloc(sizeof(struct Treenode));
}

对比一下之前的版本,是不是容易理解了许多。

Typedef 有何便利之处?

typedef#define的主要目的都是为了让代码更加简洁,也就是让代码更加美观。

除此之外,typedef还有两个优点:

  1. 参数化程序,提高可移植性。这点现在的开发用处比较少,早期计算机类的数据类型在不同的计算机上的是不同的,有些是大小,有些是数据类型的名称。如果使用typedef的话,移植的时候只要修改typedef部分即可。标准库中的size_tptrdiff_t就是两个案例。
  2. 让代码更佳易懂,因为指针在复杂数据类型中,会比较难以理解,如果使用typedef就简单多了。上一节中的talloc便是一个例子。

Typedef 与 #define 的不同之处

接下来就可以解释一下typedef#define的不同之处了。

typedef#define的主要目的都是为了让代码更加简洁,所以都有文本替换的功能。二者不同之处在于,typedef由于可以被编译器理解,所以文本替换也比宏要强大的多。

宏只能做简单的文本替换,比如直接文本替换,简单的计算和操作。下面就是一个简单的文本替换案例:

#define MAXWORD 100

int a[MAXWORD];

在编译的时候,会先直接将int a[MAXWORD];换成int a[100];,也就是文本替换,再进行编译,并不会将MAXWORD当作变量或常量去编译。所以宏所属的范围也称为预处理器(Preprocessor)。

而使用typedef的话,就可以实现一些复杂的功能。比如说下面这行代码是新建一个类型PFI,是指向有两个参数、参数类型为char *、返回值为int的函数的指针:

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

这样在声明一些函数的时候就非常方便,比如下面这个函数:

int strcmp(char *s, char *t)
{
    for ( ; *s == *t; s++, t++) {
        if (*s == '\0') {
            return 0;
        }
    }
    return *s - *t;
}

在声明的时候就可以写成:

PFI strcmp;

对比原本的

int strcmp(char *, char *);

是不是简洁了很多。如果同时有多个类似的函数,那么写在同一行也可以,更加简洁。

希望能帮到有需要的人~


http://www.kler.cn/a/15477.html

相关文章:

  • 【AI日记】24.11.17 看 GraphRAG 论文,了解月之暗面
  • 【C++滑动窗口】1248. 统计「优美子数组」|1623
  • docker 安装之 windows安装
  • 场景营销在企业定制开发 AI 智能名片 S2B2C 商城小程序中的应用与价值
  • 走进嵌入式开发世界
  • SOP搭建:企业标准化操作程序构建与实施指南
  • 下载——安装——使用FinalShell
  • 权威学者、企业CFO荟聚上海国家会计学院,共探「智能会计 价值财务」
  • 30基于非对称纳什谈判的多微网电能共享运行优化策略MATLAB程序
  • 最值得学的编程语言是哪个?
  • 10、Java继承与多态 - 内部内的概念与分类
  • hw xm 的额外symbol汇总
  • 为什么要用虚拟 DOM?
  • Open3D 最小二乘拟合二维直线
  • 智能合约的分层设计浅谈
  • 可视化CNN和特征图
  • Java 中的异常处理机制是什么?如何使用它来处理程序中的异常?(七)
  • 玩转ChatGPT:Auto-GPT项目部署与测评
  • 机器学习实战教程(十):逻辑回归
  • 手把手带你写一份优秀的开发求职简历(四)
  • 亚科转债,鹿山转债上市价格预测
  • Leetcode力扣秋招刷题路-0853
  • 能上网的ChatGPT,会带来什么改变
  • 【信息安全案例】——身份与访问安全(学习笔记)
  • HashMap为什么数组长度是2的幂
  • 如何真正认识 Linux 系统结构?这篇文章告诉你