C语言应用笔记:C语言typedef关键字及其使用

C 语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、指针类型名称与用户自定义的结构型名称、共用型名称、枚举型名称等。

一旦用户在程序中定义了自己的数据类型名称,就可以在该程序中用自己的数据类型名称来定义变量的类型、数组的类型、指针变量的类型与函数的类型等。typedef 关键字定义的名称并不是真的创造了一种数据类型,而是给已有的或者复合型的以及复杂的数据类型取一个我们更容易理解识别的别名。

typedef 关键字怎么使用?又有哪些情况可以使用?接下来我们就对它的几种用法进行说明:

(1)基本数据类型定义

也就是说,我们使用 typedef 关键字对系统默认的基本数据类型名进行重新定义。例如我们使用标准整数的数据类型 uint8_t 和 uint16_t 等时,其实它们的原始定义如下:

typedef unsigned char uint8_t;   //无符号8位整数
typedef signed char int8_t;      //有符号8位整数
typedef unsigned short uint16_t; //无符号16位整数
typedef signed short int16_t;    //有符号16位整数
typedef unsigned long uint32_t;  //无符号32位整数
typedef signed long int32_t;     //有符号32位整数

显然,使用 typedef 关键字给已有的数据类型定义了一个别名。当我们使用 uint8_t 时,就和使用 unsigned char 是一样的。此外,我们还可以使用这种方法来定义与平台无关的类型,这样,当跨平台移植程序时,我们只需要修改一下 typedef 的定义即可,而不用对其他源代码做任何修改。

(2)指针数据类型定义

有些时候我们也会使用 typedef 关键字定义指针数据类型,用来简化我们所使用的指针变量的声明,例如:

typedef int *pointer;
typedef int (*pointer)[N];
typedef int array[M][N];

上面的第1个例子中,我们定义了一个指针类型,当我们使用 pointer p 声明一个指针变量,就和使用 int *p 的含义是一样的。这个例子是一个指针变量类型,可以演化出很多用法,如定义数组对象可以更明确。有时候,我们也定义指向二维数组的指针,使用 typedef 关键字就可以使得操作更符合我们的常规认知。第2个例子中的 pointer 等价于 int (*)[N],当我们声明 pointer p 就相当于 int (*a)[N]。第3个例子的含义与指针是类似的,比如我们定义 array a 就是声明了一个 M 行 N 列的数组,此时 p = a 是可以的。

我们考虑到数组很多时候可以使用指针表示,所以将其放在一起讨论,而其他一些对象指针我们单独讨论。其实,不光是上述数组和指针可以使用 typedef 关键字定义别名,其他如:一维和多维数组,指针数组等都可以这样使用。

(3)用户对象类型定义

这里的用户对象是指结构体、联合体以及枚举等用户自定义的数据类型。我们可以使用 typedef 关键字给结构体等类型定义一个别名,这样我们可以在多个地方更方便地使用它。例如,使用 typedef 关键字为结构体类型定义一个别名:

typedef struct
{  float Kp; //比例系数    float Ki; //积分系数    float Kd; //微分系数        float Error;     //本次误差    float LastError; //上一次误差    float Diff;      //PID微分项        float Integral;    //PID积分项    float MaxIntegral; //积分上限    float MinIntegral; //积分下限        float Output;    //PID输出项    float MaxOutput; //输出上限    float MinOutput; //输出下限
} PID_TypeDef;

这样我们在需要使用结构体类型定义一个对象时,我们可以使用 PID_TypeDef 定义就可以与原始定义相同了,例如:

PID_TypeDef vPID;

同样我们也可以使用 typedef 关键字为枚举定义一个别名:

typedef enum
{ WRITE_REG = ((uint8_t)0x80), //写寄存器功能码    READ_REG = ((uint8_t)0x81),  //读寄存器功能码    WRITE_VAR = ((uint8_t)0x82), //写变量功能码    READ_VAR = ((uint8_t)0x83)   //读变量功能码
} FunctionCode;

我们需要定义枚举变量时,也是使用 FunctionCode fc 就可以了。当然,我们也可以使用定义的类型声明指针变量,或者直接有 typedef 关键字定义指向对象的指针类型,如定义结构体指针类型。

(4)函数类型定义

typedef 关键字也常用来定义函数类型,用以声明同类型的函数或者函数指针变量。这一种类型定义的函数用作形参等回调的方式使用时,非常有用,具体用法可参考回调函数的使用。

使用 typedef 关键字定义函数类型与前面的各种方式类似。例如:

typedef int fType(void);

这里 fType 等价于 int (void) 类型函数。如果我们使用 fType function 声明函数 function 时,与使用 int function(void) 来声明是一样的。

同样我们也可以使用 fType 来定义函数指针。如果我们使用 fType *fPointer 声明函数指针 fPointer 时,和使用 int (*fPoniter)(void) 来声明是一样的。

当然,我们也可以使用 typedef 关键字直接定义函数指针类型。例如:

typedef int (*fPointer)(void);

这样我们就可以使用 fPointer 来定义一个函数指针。比如我们使用 fPointer fp 声明函数指针就如同使用 int (*fp)(void) 来声明。

(5)typedef 关键字与宏定义

前面我们已经简要说了 typedef 关键字的基本用法,我们发现它的功能似乎宏定义也能实现,所以我们接下来看一下 typedef 关键字和 #define 定义的宏之间究竟有何不同。

从功能范围来讲,typedef 主要是为已经存在的关键字或者类型及其组合取一个我们容易识别的别名。在这一点上 #define 也可以实现,但除此之外 #define 还有其他用处,如果愿意的话你可以使用它定义任何代码,这是 typedef 所不具备的。

从执行时间来讲,对于 #define 定义的宏,其在预处理阶段就会被替换,而 typedef 定义的类型会在编译时处理。

从作用域上来讲,一般来说 #define 定义的宏没有作用域的限制,只要在使用前定义就可以,而 typedef 定义的别名是有作用域的。

从实现效果来讲,我们使用 typedef 定义一个指针类型,然后使用该类型可以同时声明多个变量,而 #define 却不是这样的。例如,typedef (int*) pType; 可以使用pType a, b; 这里 a 和 b 都是指向整数的指针变量。但我们同样定义 #define pType int*, 若使用 pType a, b; 定义 a 和 b,则 a 是指向整数的指针变量,而 b 不是。

还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。因此,像下面这种声明方式是不可行的:

typedef static int INT_STATIC;

原因是不能声明多个存储类关键字,由于 typedef 已经占据了存储类关键字的位置,因此,在 typedef 声明中就不能够再使用 static 或任何其他存储类关键字了。

声明:

本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java不支持发行版本12_主要发行版本后Java开发人员应使用的15种工具

java不支持发行版本12新部署的生存工具包:适用于Java开发人员的工具,这些工具经常将代码部署到生产中! Takipi会检测生产中的所有错误,并像发生错误时一样显示变量值 立即部署并获得免费的T恤 新部署的终极生存套件 与在僵尸末…

php get raw,file_get_contents(“php:// input”)或$ HTTP_RAW_POST

慕用2447696file_get_contents(php:// input) - 获取原始POST数据,你需要在编写API时使用它,并且需要XML / JSON / ...输入,这些输入无法通过PHP解码为$ _POST 一些例子:通过邮寄JSON字符串发送function fn(){var js_o…

绑定dictionary 给定关键字不再字典中_对字典嵌套的理解及二级下拉菜单的制作...

大家好,今日我们继续讲解VBA数组与字典解决方案,今日讲解第51讲:对字典嵌套的理解及二级下拉菜单的制作.在讲字典的时候,我反复说明,字典看视非常简单,由于它具有直达性可以省略去我们大量的循环查找代码,所以使用起来要特别留意很多用法和常…

C语言小笔记

C99标准下可以指定结构体的成员初始化。typedef struct{int a;int b; } Test;Test test {.a 10, .b 15};C99标准下可以指定数组下标初始化。int a[5] { [2] 5, 6, [4] 7 };方便的数据打印。打印一个整型值数据:int count 10; printf("count %d\n"…

lua中keyvalue_40行中的持久性KeyValue Server和一个可悲的事实

lua中keyvalue再次出现。..彼得斯撰写了有关Unsafe用法的书面概述 ,我将简要介绍一下Java中的低级技术如何通过启用更高级别的抽象或允许Java性能级别来节省开发工作可能很多人都不知道。 我的主要观点是表明,将对象转换为字节,反之亦然是一…

C++基础教程示例详解:C++中的I/O重定向

在C语言中,我们可以使用函数freopen()将现有文件指针重定向到另一个流。freopen()的原型如下FILE * freopen ( const char * filename, const char * mode, FILE * stream );例如,要将stdout重定向为文本文件,我们可以编写freopen ("tex…

租房界的php,php实现出租房数据管理及搜索页面

这篇文章主要为大家详细介绍了php出租房数据管理及搜索页面的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下php数据访问例子:租房信息管理,具体内容如下1.数据库建表2. zufangzi.php租房子区域:全选requi…

ln函数怎么看奇偶性_Python中函数的参数应该怎么理解?看完这篇文章情不自禁的想收藏...

前面给大家讲过,函数是一种编程思想,是提高代码重复利用的设计思路,是代码设计更深层次的产物。今天要给大家讲的就是函数的核心:函数的参数基本概念1、函数的参数:是指函数完成某项功能所需要的信息。举个例子&#x…

面向对象设计思想-C语言

面向对象的三个特征:封装,继承,多态。但是C语言不是面向对象编程语言,所以需要借助一些技巧来实现这三个特征:(1)C语言没有成员函数,struct只能封装数据,不能封装方法&am…

three.js加载3d模型_基于WebGL的3D技术在网页中的运用 ThingJS 前端开发

Three.js、ThingJS这些引擎库可以加载3D制作软件的模型&#xff0c;大幅度提高了制作效率&#xff0c;改变WebGL开发困难的局面&#xff0c;让Web开发者享受便捷的3D开发服务。三者的难度对比如下&#xff1a;ThingJS&#xff08;框架&#xff09;< Three.js&#xff08;引擎…

C语言 | typedef

C语言typedef用新的类型名代替原有的类型名//指定用Integer为类型名&#xff0c;作用与int相同。 typedef int Integer&#xff1b;//指定用Real为类型名&#xff0c;作用与float相同。 typedef float Real&#xff1b;C语言允许程序设计者用一个简单的名字代替复杂的类型形式命…

php珠心算源码,深度解析珠心算的“开智”功能

编者按&#xff1a;本文来自李绵军校长在廊坊智慧特训营演讲。李绵军校长通过十几年来对珠心算的钻研练习&#xff0c;详细解读了珠心算的开智功能&#xff0c;以及“一门深入”的作用。珠心算的开智价值是在哪里&#xff1f;大家都说开发智力&#xff0c;我在这讲开发智力不是…

C语言 函数

定义函数在 C 语言中&#xff0c;函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分&#xff1a;返回类型&#xff1a;一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值&#xff0c;在这种情况下&#xff…

自适应 幻灯片代码 app_字节跳动 To B 再添一员,将推出飞书文档独立App | 36氪独家...

不只是功能点的延伸&#xff0c;以 C 端打 B 端&#xff0c;是字节跳动推出“飞书文档”的另一体现。文&#xff5c;苏建勋头图来源| IC photo据36氪获悉&#xff0c;字节跳动旗下移动办公软件“飞书”将于近期推出独立 App “飞书文档”。这是继2月底&#xff0c;字节跳动推出…

听说高手都用记事本写C语言代码?

坊间传闻高手都喜欢用记事本写代码&#xff0c;那么问题来了&#xff0c;我们以C语言为例&#xff0c;如何用记事本编译运行呢&#xff1f;其实最简单的方式就是安装GCC编译器&#xff0c;在记事本编写C语言程序&#xff0c;然后再在命令行用GCC编译运行&#xff0c;下面我简单…

jface_使用JFace Viewer延迟获取模型元素

jfaceEclipse JFace Viewers显示的模型元素有时需要花费大量时间来加载。 因此&#xff0c; 工作台提供了IDeferredWorkbenchAdapter类型以在后台获取此类模型元素。 不幸的是&#xff0c;似乎仅通过DeferredTreeContentManager派生的AbstractTreeViewer支持此机制。 因此&…

C语言边角料:结构体中指针类型的成员变量,它的类型重要吗?

一、前言昨天在编译代码的时候&#xff0c;之前一直OK的一个地方&#xff0c;却突然出现了好几个 Warning!本着强迫症要消灭一切警告的做法&#xff0c;最终定位到&#xff1a;是结构体内部&#xff0c; 指向结构体类型的指针成员变量导致的问题。这个问题&#xff0c;也许永远…

C语言:--位域和内存对齐

位域位域是指信息在保存时&#xff0c;并不需要占用一个完整的字节&#xff0c;而只需要占几个或一个二进制位。为了节省空间&#xff0c;C语言提供了一种数据结构&#xff0c;叫“位域”或“位段”。“位域“是把一个字节中的二进位划分为几个不同的区域&#xff0c;并说明每个…

C语言实现数据字节序交换的四种方式

1关于数据字节序的说明1&#xff09;关于字节序的说明字节序有两种大端和小端。大端&#xff1a;数据高位存放在低地址&#xff0c;地位放在高地址。如0x12345678在内存中存放为地址从左到右为低到高12345678。 小端&#xff1a;数据地位存放在低地址&#xff0c;高位存放在高地…

C语言如何实现动态数组?

提出问题请问在c语言里如何实现动态大小的数组啊&#xff0c;比如说int a[N];&#xff0c;这里N的值可以在程序中定&#xff0c;或者有什么方法可以实现类似的功能&#xff1f;总之只要在编译时不用制定数组大小就行。分析问题嵌入式系统的内存是宝贵的&#xff0c;内存是否高效…