水滴石穿C语言之typedef的问题

数据结构:什么是typedef?typedef的用法?应用举例 阅读详情

  1. 基本解释

  typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。

  在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。

  至于typedef有什么微妙之处,请你接着看下面对几个问题的具体阐述。

 
 


  2. typedef & 结构的问题

  当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:

typedef struct tagNode
{
 char *pItem;
 pNode pNext;
} *pNode; 

  答案与分析:

  1、typedef的最简单使用

typedef long byte_4;

  给已知数据类型long起个新名字,叫byte_4。

  2、 typedef与结构结合使用

typedef struct tagMyStruct
{
 int iNum;
 long lLength;
} MyStruct;

  这语句实际上完成两个操作:

  1) 定义一个新的结构类型

struct tagMyStruct
{
 int iNum;
 long lLength;
};

  分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,struct 关键字和tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。

  我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。

  2) typedef为这个新的结构起了一个名字,叫MyStruct。

typedef struct tagMyStruct MyStruct;

  因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。

  答案与分析

  C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。

  根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。

  解决这个问题的方法有多种:

  1)、

typedef struct tagNode
{
 char *pItem;
 struct tagNode *pNext;
} *pNode;

  2)、

typedef struct tagNode *pNode;
struct tagNode
{
 char *pItem;
 pNode pNext;
};

  注意:在这个例子中,你用typedef给一个还未完全声明的类型起新名字。C语言编译器支持这种做法。

  3)、规范做法:

struct tagNode
{
 char *pItem;
 struct tagNode *pNext;
};
typedef struct tagNode *pNode;

  3. typedef & #define的问题

  有下面两种定义pStr数据类型的方法,两者有什么不同?哪一种更好一点?

typedef char *pStr;
#define pStr char *; 

  答案与分析:

  通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:

typedef char *pStr1;
#define pStr2 char *;
pStr1 s1, s2;
pStr2 s3, s4;

  在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。

  #define用法例子:

#define f(x) x*x
main( )
{
 int a=6,b=2,c;
 c=f(a) / f(b);
 printf("%d /n",c);
}

  以下程序的输出结果是: 36。

  因为如此原因,在许多C语言编程规范中提到使用#define定义时,如果定义中包含表达式,必须使用括号,则上述定义应该如下定义才对:

#define f(x) (x*x)

  当然,如果你使用typedef就没有这样的问题。

  4. typedef & #define的另一例

  下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?

typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;

  答案与分析:

  是p2++出错了。这个问题再一次提醒我们:typedef和#define不同,它不是简单的文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和const long x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。

(注:关于const的限定内容问题,在本系列第二篇有详细讲解)。

  #define与typedef引申谈

  1) #define宏定义有一个特别的长处:可以使用 #ifdef ,#ifndef等来进行逻辑判断,还可以使用#undef来取消定义。

  2) typedef也有一个特别的长处:它符合范围规则,使用typedef定义的变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而宏定义则没有这种特性。

  5. typedef & 复杂的变量声明

  在编程实践中,尤其是看别人代码的时候,常常会遇到比较复杂的变量声明,使用typedef作简化自有其价值,比如:

  下面是三个变量的声明,我想使用typdef分别给它们定义一个别名,请问该如何做?

>1:int *(*a[5])(int, char*);
>2:void (*b[10]) (void (*)());
>3. doube(*)() (*pa)[9];

  答案与分析:

  对复杂变量建立一个类型别名的方法很简单,你只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了。

  (注:如果你对有些变量的声明语法感到难以理解,请参阅本系列第十篇的相关内容)。

>1:int *(*a[5])(int, char*);
//pFun是我们建的一个类型别名
typedef int *(*pFun)(int, char*);
//使用定义的新类型来声明对象,等价于int* (*a[5])(int, char*);
pFun a[5];

>2:void (*b[10]) (void (*)());
//首先为上面表达式蓝色部分声明一个新类型
typedef void (*pFunParam)();
//整体声明一个新类型
typedef void (*pFun)(pFunParam);
//使用定义的新类型来声明对象,等价于void (*b[10]) (void (*)());
pFun b[10];

>3. doube(*)() (*pa)[9];
//首先为上面表达式蓝色部分声明一个新类型
typedef double(*pFun)();
//整体声明一个新类型
typedef pFun (*pFunParam)[9];
//使用定义的新类型来声明对象,等价于doube(*)() (*pa)[9];
pFunParam pa; 

autoware 激光-相机联合标定 autoware进行激光-相机联合标定 ~~~ 刚开始进行激光-相机联合标定的时候,出现了不少问题,在此记录一下整体标定流程,以防忘记。在此,特别感谢佳明师弟,在录制数据集时提供的帮助。 ~~~ 0.系统配置: Ubuntu18.04系统 ROS Melodic opencv 3.2.0 vlp-16 一.安装autoware 这部分网上教程挺多的,但我在编译的过程中仍存在不少bug,唉~_~。 二.安装calibration_camera_lidar,从a... 阅读详情

相关推荐

GD32F303串口DMA发送数据避坑指南:为什么你的发送函数会卡住?

本文深入解析GD32F303单片机串口DMA发送数据时常见的卡死问题,提供详细的避坑指南。从DMA传输完成中断时序、发送状态管理到双通道DMA的特别注意事项,全面剖析问题根源并给出解决方案,帮助开发者构建健壮的DMA发送机制。

weixin_27038245的博客 294

14、typedef 用法总结

1、typedef使用示例 typedefinta[10];typedefvoid(*p)(void) typedefintFun(); 定义了一个函数类型Fun,所有这个类型的函数都返回一个int类型的值。 再如: intsum(inta,intb) { return(a+b); } intsub(inta,intb) { ...

hopegrace的博客 835

【软件逆向】带壳带反调试找flag教程(VMProtect3.0+X64dbg+ScyllaHide)

【软件逆向】带壳带反调试找flag教程(VMProtect 3.0+X64dbg+ScyllaHide)

zhangjiuding的博客 7508

typedef void (*p)(void)说明

#include "stdio.h" void print(void) { printf("print\n"); } void PRINT(void) { printf("PRINT\n"); } //定义了一个别名为p0的函数指针 typedef void (*p0)(void); //使用时要定义一个变量p0 p; /*******************************************************************/ int (*p1)(int c,in

qq_45955402的博客 1926

windows10系统上安装最新版mysql 8.0详细步骤

windows10系统上安装最新版mysql 8.0详细步骤

glei20的博客 6715

uniapp | vue2 | vue3 - 解决调用天地图功能服务时 http 网络请求报错 net::ERR ABORTED 503(Service Temporarily Unavailabl)

vue,uni-app,天地图,请求报错,503,请求失败,map.tianditu,天地图503,天地图请求503,接口503错误怎么办,vue天地图,uniAPP天地图,获取定位接口服务器报错503,获取当前定位,定位功能,IP属地定位,天地图服务器报错,如何解决报错,net::ERRABORTED503(ServiceTemporarilyUnavailabl),GET,POST,服务暂时不可用,react天地图,一直等待吗,报错怎么办,定位报错,轨迹,经纬度,天地图服务器503,在vue2

🏆 前端领域优质创作者 4438

C语言指针(二)

C语言有关指针的部分知识(加强版)

weixin_57418095的博客 869

基于YOLOv11与相机标定的齿轮尺寸测量系统

本文详细介绍了一种基于深度学习的目标检测算法YOLOv11与相机标定技术相结合的齿轮尺寸自动测量系统。该系统能够实时检测图像中的齿轮目标,并精确测量其关键尺寸参数,包括齿顶圆直径、齿根圆直径、模数等。我们构建了完整的深度学习解决方案,包含数据采集与标注、模型训练、相机标定、尺寸测量算法以及用户友好的UI界面。本文提供了完整的代码实现,并推荐了相关的参考数据集,为工业视觉检测领域提供了实用的技术方案。关键词:YOLOv11;齿轮检测;尺寸测量;相机标定;深度学习;工业视觉python。

YOLO 411

C/C++ typedef的理解 typedef void (*pfunc)(int);

C/C++ typedef的理解 typedef void (*pfunc)(int); 初学时: typedef int XXX,给类型int取一个别名xxx,嗯我懂了,EZ。 一段时间过后: typedef void (*pfunc)(int); ???将void取别名(*p...

qq_42174306的博客 1402

Open3D 高斯牛顿法优化的ICP点云配准

本文介绍了基于高斯牛顿法的ICP点云配准算法。算法通过最小化源点云与目标点云之间的误差函数,求解最优的刚性变换参数(平移向量和欧拉角)。核心内容包括:1)建立误差函数和目标函数;2)推导雅可比矩阵计算,特别是旋转导数的李代数近似;3)详细阐述高斯牛顿法的迭代流程,包括变换计算、最近邻搜索、参数更新等步骤;4)分析算法的优缺点,指出其具有二阶收敛速度但可能陷入局部最优。最后给出了完整的数学推导过程,包括误差函数的泰勒展开和目标函数的近似优化。该算法适用于三维点云配准任务,但需要良好的初始位姿以避免局部收敛问题

点云侠的博客 128

ABAP Reduced Message Types:用精简 IDoc + Change Pointer,把主数据分发做得又快又省

本文介绍了SAP系统集成中主数据分发的精简优化方法。通过创建"精简消息类型"(Reduced Message Types),可以在不改标准IDoc类型的前提下,只发送接收系统真正需要的数据。文章详细解析了主数据变更链路的完整流程,包括变更文档、变更指针和IDoc生成机制,并重点说明了如何在BD53事务中创建精简消息类型、选择保留字段、激活变更指针等实操步骤。此外,还介绍了通过BD59过滤对象和BD64分发模型实现更精确的数据分发,以及变更指针的激活验证、IDoc生成作业和定期清理等运维要

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 132

【Codecs系列】x265编码器(十二):子像素运动搜索

在基于块运动补偿的视频编码框架中,运动搜索是最为重要的环节之一,同时也是编码端最为耗时的模块。运动搜索包括整像素运动搜索和子像素运动搜索,其中整像素运动搜索已经有很多快速算法,比如经典的三步搜索法、菱形搜索、六边形搜索以及TZSearch等等;但子像素搜索的快速算法却比较少,本文主要讲解x265编码器中的子像素搜索方法以及相关的快速搜索方法。

优快云明星博主,认证博客专家,视频、Matlab领域优质创作者。 747

C语言之typedef的问题

 水滴石穿C语言之typedef的问题                                        1. 基本解释  typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。  在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一

yongzi123的专栏 1596

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

typedef

水滴石穿C语言之typedef的问题   1. 基本解释typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的

SN1130的专栏 607

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

水滴石穿C语言之正确使用const

  问题:const变量 & const 限定的内容  下面的代码编译器会报一个错误,请问,哪一个语句是错误的呢?typedef char * pStr;char string[4] = "abc";const char *p1 = string;const pStr p2 = string;p1++;p2++;   答案与分析:  问题出在p2++上。  1)、const使用的基本形式: con

小发猫 1308

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【C语言初阶】万字解析,带你0基础快速入门C语言(下)

全程干货,从安装开始教你如何0基础快速入门C语言,其中包含思维导图,注释图等内容保证让你看懂并理解所讲内容。超级适合0基础小白自学!!!

君兮_的博客 979

C底层编程

水滴石穿C语言之C语言的底层操作 概述  C语言的内存模型基本上对应了现在von Neumann(冯·诺伊曼)计算机的实际存储模型,很好的达到了对机器的映射,这是C/C++适合做底层开发的主要原因,另外,C语言适合做底层开发还有另外一个原因,那就是C语言对底层操作做了很多的的支持,提供了很多比较底层的功能。   下面结合问题分别进行阐述。   问题:移位操作   在运用移位操作符时,有

小小学的专栏 5792

C语言指针进阶(一)——深入详解“函数指针”与“指针函数”

前言:C语言最难的地方莫过于各种类型的指针,光听名字就把人给绕晕了,本文是在一些重要的基础概念之上进行说明的,需要一些知识储备,即:什么是数组指针、指针数组、函数指针、指针函数等,然后才能看得懂本文。 一、简单概述 1.1 函数指针 所谓函数指针即定义一个指向函数的指针变量,定义的格式如下: int (*p)(int x, int y); //注意:这里的括号不能掉,因为括号()...

MIss-Y的博客 10万+
上一篇: C语言程序设计基础之结构
下一篇: C程序设计基础之多维数组的指针变量
普通网友
博客等级 码龄22年 1万+粉丝 3156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值