C语言学习及应用笔记之五:C语言typedef关键字及其使用

在C语言中有一个typedef关键字,其用来定义用户自定义类型。当然,并不是真的创造了一种数据类型,而是给已有的或者符合型的以及复杂的数据类型取一个我们自己更容易理解的别名。总之,可以使用typedef关键字定义一个我们自己的类型名称。

那么,究竟如何定义,又有哪些情况下可已使用呢?接下来我们就对它的几种用法进行说明:

(1)基本数据类型定义

有些时候,我们会使用typedef关键字对一些基本数据类型进行重新定义。例如我们使用标准整数的数据类型uint8_t和uint16_t等时,其实他们的定义如下:

typedef  unsigned char   uint8_t;     //无符号8位数

typedef  signed   char   int8_t;      //有符号8位数

typedef  unsigned int    uint16_t;    //无符号16位数

typedef  signed   int    int16_t;     //有符号16位数

typedef  unsigned long   uint32_t;    //无符号32位数

typedef  signed   long   int32_t;     //有符号32位数

很显然就是使用了typedef关键字给既有数据类型分配了一个别名。当我们使用uint8_t时,就和使用unsigned char是一样的。如我们声明uint8_t var时,和使用unsigned char var是一回事。

(2)指针数据类型定义

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

例如:typedef int *pointer;

这样我们就定义了一个指针类型,当我们使用pointer p声明一个指针变量,就和使用int *p的含义是一样的。

上面是一个指针变量类型,可以演化出很多用法,如定义数组对象可以更明确。有时候,我们也定义指向二位数组行的指针,使用typedef关键字就可以使得操作更符合我们的常规认知。

例如: typedef int (*pointer)[N];

这里pointer等价于 int (*)[N],当我们声明pointer p就相当于声明int (*a)[N]。同样的,如果我们对二维数组采用类似的定义。

例如:typedef int array[M][N];

那它的含义与指针是类似的,如我们定义array a就是声明了一个M行N列的数组,此时使用p=a是可以的。

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

(3)用户对象类型定义

首先说明,这里说所的用户对象是指结构体、联合体以及枚举等用户定义的数据类型。我们可以使用typedef关键字给结构体等类型定义一个别名,这样我们客气在多个地方更方便的使用它。当然很多人对此有不同看法,这里不讨论,我们只是说有这种用法。

使用typedef关键字为结构体类型定义一个别名。

例如:typedef struct{

  float setpoint;               /*设定值*/

  float kp;                     /*比例系数*/

  float ki;                     /*积分系数*/

  float kd;                     /*微分系数*/

  float lasterror;              /*前一拍偏差*/

  float preerror;               /*前两拍偏差*/

  float deadband;               /*死区*/

  float result;                 /*PID控制器计算结果*/

  float output;                 /*输出值0-100%*/

  float maximum;                /*输出值上限*/

  float minimum;                /*输出值下限*/

  float errorabsmax;            /*偏差绝对值最大值*/

  float errorabsmin;            /*偏差绝对值最小值*/

  float alpha;                  /*不完全微分系数*/

  float deltadiff;              /*微分增量*/

  float integralValue;          /*积分累计量*/

  float gama;                   /*微分先行滤波系数*/

  float lastPv;                 /*上一拍的过程测量值*/

  float lastDeltaPv;            /*上一拍的过程测量值增量*/

}CLASSICPID;

这样我们在需要使用结构体类型定义一个对象时,我们可以使用CLASSICPID vPID就可以了与使用原始定义是一样的。

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

例如:typedef enum {

  FC_REG_Write=((uint8_t)0x80),         /*写寄存器的功能码*/

  FC_REG_Read=((uint8_t)0x81),          /*读寄存器的功能码*/

  FC_VAR_Write=((uint8_t)0x82),         /*写变量的功能码*/

  FC_VAR_Read=((uint8_t)0x83),          /*读变量的功能码*/

  FC_Curve_Write=((uint8_t)0x84)        /*写曲线缓冲区的功能码*/

}DwinFunctionCode;

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

(4)函数类型定义

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

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

例如: typedef int fType(void);

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

同样我们也可以使用fType来定义函数指针。如果我们使用fType *fPointer声明函数指针fPointer时,和使用int (*fPointer) (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不是。

欢迎关注:

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

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

相关文章

Modbus协议栈开发笔记之五:Modbus RTU Slave开发

Modbus在串行链路上分为Slave和Master,这一节我们就来开发Slave。对于Modbus RTU从站来说,需要实现的功能其实与Modbus TCP的服务器端是一样的。其操作过程也是一样的。首先接收到主站的访问命令,对该命令报文进行解析,这里我们也…

Modbus协议栈开发笔记之六:Modbus RTU Master开发

这一节我们来封装最后一种应用(Modbus RTU Master应用),RTU主站的开发与TCP客户端的开发是一致的。同样的我们也不是做具体的应用,而是实现RTU主站的基本功能。我们将RTU主站的功能封装为函数,以便在开发具体应用时调用…

PID控制器开发笔记之十三:单神经元PID控制器的实现

神经网络是模拟人脑思维方式的数学模型。神经网络是智能控制的一个重要分支,人们针对控制过程提供了各种实现方式,在本节我们主要讨论一下采用单神经元实现PID控制器的方式。 1、单神经元的基本原理 单神经元作为构成神经网络的基本单位,具…

基于STM32L476的锂电池SOC检测

便携式设备由于使用需求而配备了锂电池,但使用过程中需要掌握电源的状态才能保证设备正常运行。而且在电池充放电的过程中,监控电池的充放电状态也是保证设备安全的需要。 1、硬件设计 电池SOC检测是一个难题,有很多的模型和检测电路。但对…

C语言学习及应用笔记之六:C语言extern关键字及其使用

在C语言中,修饰符extern用在变量或者函数的声明前,用来以标识变量或者函数的定义在别的文件中,提示编译器遇到此变量或者函数时,在其它文件中寻找其定义。extern关键字的用法有几种,我们下面对其进行说明。 1、extern…

C语言学习及应用笔记之七:C语言中的回调函数及使用方式

我们在使用C语言实现相对复杂的软件开发时,经常会碰到使用回调函数的问题。但是回调函数的理解和使用却不是一件简单的事,在本篇我们根据我们个人的理解和应用经验对回调函数做简要的分析。 1、什么是回调函数 既然谈到了回调函数,首先我们…

STM32与SHT1X温湿度传感器通讯

在这次项目开发中应用到了SHT1X温湿度传感器,该系列有SHT10、SHT11和SHT15,属于Sersirion温湿度传感器家族中的贴片封装系列。包括一个电容性聚合体测湿敏感元件、一个用能隙材料制成的测温元件,传感器内部有一个精度高达14为位的A/D转换器。…

STM32与MS5837压力传感器的I2C通讯

MS5837压力传感器是一种可用于电路板上,适用于检测10-1200mbar压力范围的传感器,灵敏度非常高,理论上能够检测到0.01mbar的压力变化,实际使用过程中测试并无明显的变化。 MS5837采用I2C总线通讯,与STM32的MCU可以实现…

STM32F0使用LL库实现MS5536C通讯

在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。在本文中我们说明一下,使用LL库实现MS5536C的SPI通讯。 1、MS5536C简述 MS5536C是…

STM32F0使用LL库实现DMA方式AD采集

在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。在本文中我们将介绍基于LL库的ADC的DMA采集方式。 1、概述 这次我们使用DMA方式实现对AD的采集…

STM32与宇电设备实现AI-BUS通讯

宇电的设备使用基于RS-485的自定义协议,协议本身比较简单,只有2条指令: 读:地址代号52H(82) 要读的参数代号00校验码 写:地址代号43H(67)要写的参数代号写入数低字节写…

FreeRTOS如何结束和重新启动调度程序

大多数主机或桌面系统(比如Linux,Mac或Windows)都有一个正常的用例,你可以在早上启动操作系统,然后在晚上关闭它,然后你就离开机器。嵌入式系统是不同的:他们没有参加,他们应该“永远…

先进过程控制之一:浅说APC

先进过程控制(APC)技术作为在生产装置级的信息化应用,在优化装置的控制水平和提高生产过程的管理水平的同时,还为企业创造了可观的经济效益。 1、什么是APC 先进过程控制,简称APC,并不是什么新概念。它仅…

STM32与多台MS5803压力传感器I2C通讯

MS5803压力传感器支持SPI和I2C总线通讯,拥有24位AD转换。能够同时获得压力值和温度值,其中压力测量范围为10-1100mbar,温度的测量范围是-40-85摄氏度。各引脚功能及参数如下: 传感器内部结构图如下: 通讯协议的选择通过…

STM32F0使用LL库实现SHT70通讯

在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。本篇我们将基于LL库采用模拟I2C接口的方式实现温湿度采集。 1、SHT70简述 SHT70是一款集温湿度…

STM32F0使用LL库实现PWM输出

在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。本文我们将说明如何通过LL库实现PWM信号的输出。 1、概述 我们知道STM32的TIM计时器可以输出P…

STM32F0使用LL库实现Modbus通讯

在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。本篇将说明基于LL实现USART通讯。 1、概述 我们想要实现基于RS485的Modbus通讯实际就是基于US…

STM32基于SPI和AD7192的数据采集

在开发臭氧发生器的时,我们需要一个高分辨率的AD采集,于是选择了AD7192,选择这款ADC的原因比较简单。首先它是24位的符合我们的精度要求;其次它自带时钟,便于节省空间;第三它有4路单端或2路差分输入&#x…

Modbus协议栈实现Modbus RTU多主站支持

前面我们已经详细讲解过Modbus协议栈的开发过程,并且利用协议栈封装了Modbus RTU主站和从站,Modbus TCP服务器与客户端,Modbus ASCII主站与从站应用。但在使用过程中,我们发现一些使用不便和受限的地方,所以我们就想要…

STM32基于AD5663的UV灯电压控制

在开发臭氧发生器的时,我们使用UV灯来实现臭氧的产生。而UV灯的强度决定了臭氧产生的浓度,UV灯的光强则与其控制电压密切相关。所以我们要控制产生的臭氧的浓度就需要调节其控制电压。我们选择了AD5663这一模拟量输出模块来实现这一点。 1、AD5663简介 …