C语言菜鸟入门·各种typedef用法超详细解析

目录

1.  什么是typedef

2.  typedef的用法

2.1  对于数据类型的重定义

2.2  对于函数的重定义

2.3  对于指针的重定义

2.4  对于数组指针的重定义

2.5  对于指针数组的重定义

2.6  对于结构体的重定义(typedef struct)

2.6.1  对结构体起别名

2.6.2  对结构体指针起别名

2.6.3  汇总

2.7  对于共用体的重定义(typedef union)

2.8  对于枚举变量的重定义(typedef enum)


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;
}

        注意,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;
}

        可以看到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]); // 输出 7return 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;
}

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 重定义为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;
}

        这里可以使用箭头操作符 -> 访问结构体指针所指向的成员,发现也能正常取值:

2.6.3  汇总

代码一:

#include <stdio.h>struct student
{char name[20];int age;char sex[7];int* score;  // 例子:添加一个指向整数的指针成员
};typedef struct student stu;
typedef struct student* pdata;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)); // 访问指针成员并输出其值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;
}


 代码二:

上文我们也提到了:

struct LNode{ElemType data;struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode *LinkList;

等价于:

struct LNode{ElemType data;struct LNode *next;
}LNode,*LinkList;

那么我们可以更改代码为:

#include <stdio.h>typedef struct student
{char name[20];int age;char sex[7];int* score;  // 例子:添加一个指向整数的指针成员
}stu, * pdata;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)); // 访问指针成员并输出其值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;
}

        可以发现值并未发生改变:

2.7  对于共用体的重定义(typedef union)

        用法与结构体类似,我们对共用体 union un 重定义为 u ,并通过 u 声明变量共用体变量 b 并进行初始化。

#include<stdio.h>union un
{char a;int b;
};typedef union un u;int main()
{u b = { 0 };b.a = 'a';printf("%d", b.b);return 0;
}

        也可以将其写为:

#include<stdio.h>
typedef union un
{char a;int b;
}u;
int main()
{u b = { 0 };b.a = 'a';printf("%d", b.b);return 0;
}

2.8  对于枚举变量的重定义(typedef enum)

        使用方法也可结构体类似,具体可以参考结构体的用法,下面是个简单的例子:

#include<stdio.h>
enum week
{one = 1,two,three,four,five,six,seven
};
typedef enum week w;
int main()
{w a = one;printf("%d", a);return 0;
}

        也可以写为:

#include<stdio.h>
typedef enum week
{one = 1,two,three,four,five,six,seven
}w;
int main()
{w a = one;printf("%d", a);return 0;
}

C语言_时光の尘的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1539592.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

2.4 数据库表字段约束

一、数据库三大范式 我们构造数据库的时候必须要遵守一定的原则&#xff0c;那这个规则就是范式关系型数据库&#xff0c;一共有六种范式&#xff0c;一般情况下只需要满足第三范式即可。 ​第一范式&#xff1a;原子性构造数据库必须遵循一定的规则&#xff0c;这种规则就是…

语音识别与语音控制的原理介绍

硬件平台 机器硬件&#xff1a;OriginBot(导航版/视觉版)PC主机&#xff1a;Windows&#xff08;>10&#xff09;/Ubuntu(>20.04)扩展硬件&#xff1a;X3语音版 运行案例 首先进入OriginBot主控系统&#xff0c;运行一下指令。请注意&#xff0c;部分操作OriginBot内暂…

深度学习笔记(8)预训练模型

深度学习笔记&#xff08;8&#xff09;预训练模型 文章目录 深度学习笔记&#xff08;8&#xff09;预训练模型一、预训练模型构建一、微调模型&#xff0c;训练自己的数据1.导入数据集2.数据集处理方法3.完形填空训练 使用分词器将文本转换为模型的输入格式参数 return_tenso…

docker从容器提取镜像并上传至dockerhub

一、使用commit从容器中提取镜像 例如 //docker commit 容器名 想要创建的镜像名:版本号 docker commit epsilon_planner epsilon_planner:latest导出完成后镜像如图所示 二、登陆dockerhub并创建仓库 登陆dockerhub&#xff0c;点击Create repository创建仓库&#xff0c…

【机器学习(八)】分类和回归任务-因子分解机(Factorization Machines,FM)-Sentosa_DSML社区版

文章目录 一、算法概念二、算法原理&#xff08;一&#xff09; FM表达式&#xff08;二&#xff09;时间复杂度&#xff08;三&#xff09;回归和分类 三、算法优缺点&#xff08;一&#xff09;优点&#xff08;二&#xff09;缺点 四、FM分类任务实现对比&#xff08;一&…

【ShuQiHere】 探索数据挖掘的世界:从概念到应用

&#x1f310; 【ShuQiHere】 数据挖掘&#xff08;Data Mining, DM&#xff09; 是一种从大型数据集中提取有用信息的技术&#xff0c;无论是在商业分析、金融预测&#xff0c;还是医学研究中&#xff0c;数据挖掘都扮演着至关重要的角色。本文将带您深入了解数据挖掘的核心概…

机械设备产品资料方案介绍小程序系统开发制作

设备产品资料介绍小程序系统&#xff0c;是一家工业机械设备生产厂家为了更好的服务客户而定制开发的一套小程序系统&#xff0c;让用户通过小程序就可以了解公司产品介绍的详细参数、售后服务和产品操作手持等。 该小程序系统里面主要开发的功能模块有&#xff1a; 1、产品目…

智慧课堂学生行为数据集

智慧校园数据集合集概述 智慧校园旨在通过整合先进的信息技术来提升教育环境的安全性、效率以及互动性。一个关键组成部分是利用计算机视觉技术对校园内的各种活动进行监控与分析。为此&#xff0c;构建了一个全面的数据集合集&#xff0c;包含了密集行人、头部检测、抽烟行为…

一个手机号注册3个抖音号的绿色方法?一个人注册多个抖音号的方法!

下面这是我注册的新账号&#xff0c;显示未实名&#xff0c;在手机号这里显示辅助手机号绑定&#xff0c;手机号绑定这里显示未绑定。如果你需要矩阵&#xff0c;那么&#xff0c;还需要设置好头像&#xff0c;以及介绍&#xff0c;这些都可以正常设置。 再好的方法&#xff0c…

C++笔记21•C++11的新特性•

相比于 C98/03&#xff0c;C11则带来了数量可观的变化&#xff0c;其中包含了约140个新特性&#xff0c;以及对C03标准中约600个缺陷的修正&#xff0c;这使得C11更像是从C98/03中孕育出的一种新语言。相比较而言&#xff0c;C11能更好地用于系统开发和库开发、语法更加泛华和简…

VS code 创建与运行 task.json 文件

VS code 创建与运行 task.json 文件 引言正文创建 .json 文件第一步第二步第三步 运行 .json 文件 引言 之前在 VS code EXPLORER 中不显示指定文件及文件夹设置&#xff08;如.pyc, pycache, .vscode 文件&#xff09; 一文中我们介绍了 settings.json 文件&#xff0c;这里我…

唯徳知识产权管理系统 UploadFileWordTemplate 任意文件读取

0x01 漏洞描述&#xff1a; 唯徳于2014年成立&#xff0c;是专业提供企业、代理机构知识产权管理软件供应商&#xff0c;某公司凭借领先的技术实力和深厚的专利行业积累&#xff0c;产品自上市推广以来&#xff0c;已为1000多家企业及代理机构提供持续稳定的软件服务。其知识产…

安卓13长按电源按键直接关机 andriod13不显示关机对话框直接关机

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 有些设备需要在长按电源键的时候,直接关机。不需要弹出对话框进行询问。 2.问题分析 过滤电源按键,需要在系统里面处理的话,那么我们需要熟悉android的事件分发,然后再…

L67 【哈工大_操作系统】操作系统历史 学习任务

L6 操作系统历史 线条一 1、上古神机 IBM7094 专注于计算批处理操作系统&#xff08;Batch system&#xff09; 2、OS/360 一台计算机干多种事&#xff0c;多道程序作业之间的 切换和调度 成为核心 &#xff08;多进程结构和进程管理概念萌芽&#xff01;&#xff09; 3…

链式栈讲解

文章目录 &#x1f34a;自我介绍&#x1f34a;链式栈入栈和出栈linkstack.hlinkstack.c 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xff08;一键四连&#xff09;哦~ &#x1f34a;自我介绍 Hello,大家好&#xff0c;我是小珑也要…

《黑神话悟空》开发框架与战斗系统解析

本文主要围绕《黑神话悟空》的开发框架与战斗系统解析展开 主要内容 《黑神话悟空》采用的技术栈 《黑神话悟空》战斗系统的实现方式 四种攻击模式 连招系统的创建 如何实现高扩展性的战斗系统 包括角色属性系统、技能配置文件和逻辑节点的抽象等关键技术点 版权声明 本…

考研数据结构——C语言实现有向图邻接矩阵

首先&#xff0c;定义了一些基本的数据结构和常量&#xff1a; VertexType&#xff1a;顶点的数据类型&#xff0c;这里定义为char。EdgeType&#xff1a;边的数据类型&#xff0c;这里定义为int&#xff0c;用于存储权重。MAXVEX&#xff1a;定义了图中最大顶点数为100。INFIN…

详细解读,F5服务器负载均衡的技术优势

在现代大规模、高流量的网络使用场景中&#xff0c;为应对高并发和海量数据的挑战&#xff0c;服务器负载均衡技术应运而生。但凡知道服务器负载均衡这一名词的&#xff0c;基本都对F5有所耳闻&#xff0c;因为负载均衡正是F5的代表作&#xff0c;换句通俗易懂的话来说&#xf…

前端vue-关于标签切换的实现

首先是循环&#xff0c;使用v-for“&#xff08;item,index) in list” :key“item.id” 然后当点击哪个的时候再切换&#xff0c;使用v-bind:class" "或者是:class" ",如果都是用active的话&#xff0c;那么每一个标签都是被选中的状态&#xff0c;…

Android IME输入法启动显示隐藏流程梳理

阅读Android AOSP 12版本代码&#xff0c;对输入法IME整体框架模块进行学习梳理&#xff0c;内容包含输入法框架三部分IMM、IMMS、IMS的启动流程、点击弹出流程、显示/隐藏流程&#xff0c;以及常见问题和调试技巧。 1. IME整体框架​​​​​​​ IME整体分为三个部分&#xf…