在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不是。

欢迎关注:

C语言学习及应用笔记之五:C语言typedef关键字及其使用的更多相关文章

  1. C语言学习及应用笔记之一:C运算符优先级及使用问题

    C语言中的运算符绝对是C语言学习和使用的一个难点,因为在2011版的标准中,C语言的运算符的数量超过40个,甚至比关键字的数量还要多.这些运算符有单目运算符.双目运算符以及三目运算符,又涉及到左结合和 ...

  2. GO语言学习(十六)Go 语言结构体

    Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图 ...

  3. C语言学习书籍推荐《C程序设计语言(第2版•新版)》下载

    克尼汉 (作者), 等 (作者, 译者), 徐宝文 (译者) 下载地址:点我 <C程序设计语言(第2版•新版)>是由C语言的设计者Brian W.Kernighan和Dennis M.Ri ...

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

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

  5. C语言学习及应用笔记之三:C语言const关键字及其使用

    在C语言程序中,const关键字也是经常会用到的一个关键字,那么使用const关键字的目的是什么呢?事实上,在程序中使用const关键字的主要目的就是为了向使用者传递设计者的一些意图. 事实上,无论我 ...

  6. C语言学习及应用笔记之二:C语言static关键字及其使用

    C语言有很多关键字,大多关键字使用起来是很明确的,但有一些关键字却要相对复杂一些.我们这里要说明的static关键字就是如此,它的功能很强大,相应的使用也就更复杂. 一般来说static关键字的常见用 ...

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

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

  8. C语言学习及应用笔记之四:C语言volatile关键字及其使用

    在C语言中,还有一个并不经常使用但却非常有用的关键字volatile.那么使用volatile关键字究竟能干什么呢?接下来我将就此问题进行讨论. 一个使用volatile关键字定义变量,其实就是告诉编 ...

  9. C语言程序设计做题笔记之C语言基础知识(下)

    C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...

随机推荐

  1. 关于mysql中的count()函数

    1.count()函数是用来统计表中记录的一个函数,返回匹配条件的行数. 2.count()语法: (1)count(*)---包括所有列,返回表中的记录数,相当于统计表的行数,在统计结果的时候,不会 ...

  2. echarts报表显示%+没有0

    function showTablegroup(page) { var series; $.ajax({ type:'post', url:"<%=basePath%>flowA ...

  3. spark-MLlib之协同过滤ALS

    协同过滤与推荐   协同过滤是一种根据用户对各种产品的交互与评分来推荐新产品的推荐系统技术.   协同过滤引入的地方就在于它只需要输入一系列用户/产品的交互记录:   无论是显式的交互(例如在购物网站 ...

  4. object.observe被废弃了怎么办

    用新的 Proxy 具体见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

  5. JarvisOJ Misc shell流量分析

    分析一下shell流量,得到flag 看着一大推的数据记录头都大了,并没有什么wireshark的使用经验,开始胡搞 首先用notepad++打开,搜索flag字样找到了一个类似于python脚本的东 ...

  6. python之面向对象初识

    一.面向对象初识 1.结构上 面向对象分成两部分:属性.方法 class A: name = 'xiaoming' # 静态属性.静态变量.静态字段. def func1(self): # 函数.动态 ...

  7. linux下find命令的使用和总结

    背景:find命令十分的好用,特别是在查找文件的时候,这个时候需要和文件通配符一起使用. 1 前言 我们为什么要学会使用find命令? 每一种操作系统都有成千上万的文件组成,对于linux这样“一切皆 ...

  8. Django ORM操作补充

    操作补充 only 只取某些去除其他 defer 去除某些取其他 # 需求: 只取某n列 queryset=[ {},{}] models.User.objects.all().values( 'id ...

  9. Input标签使用整理

    0 写在前面 对于程序而言I/O是一个程序的重要组成部分.程序的输入.输出接口,指定了程序与用户之间的交互方式.对于前端开发而言,input标签也有着其重要地位,它为用户向服务端提交数据提供了可能. ...

  10. 微服务与容器化Docker

    1.Docker的应用案例 2. 3. 4.docker的核心:镜像.仓库.容器 Build构建镜像:类似于集装箱. Ship运输镜像,仓库:类似于码头.将镜像运输到仓库. Run运行镜像:容器:类似 ...