菜鸟资源网站全面焕新升级啦!全新的界面设计,简洁而不失雅致,让您一目了然,轻松上手。我们还对资源分类进行了细致梳理,确保各类资源条理清晰,便于您按需筛选与查找。 立即查看

第十三章:typedef 使用的陷阱,了解C++基本语言特性变量和类型

第十三章:typedef 使用的陷阱,了解C++基本语言特性变量和类型

  无论在 C 还是在 C++代码中,typedef 都是出现频率较多的一个关键字。typedef本身的功能是很容易理解的,其主要功能是定义一个已存在类型的别名,但是和宏并存,问题就变得复杂了。再加上国内一些教科书的问题,导致一些编程人员将...

当前版本

软件大小

软件语言

是否破解

  无论在 C 还是在 C++代码中,typedef 都是出现频率较多的一个关键字。typedef本身的功能是很容易理解的,其主要功能是定义一个已存在类型的别名,但是和宏并存,问题就变得复杂了。再加上国内一些教科书的问题,导致一些编程人员将宏和typedef 混为一谈.

  typedef 有助于创建平台无关类型,甚至能隐藏复杂和难以理解的语法。使用typedef 可编写出更加美观和可读的代码。所谓美观,意指 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性以及未来的可维护性。本实用经验将竭尽全力来揭示typedef 的强大功能以及如何避免一些常见的使用陷阱。

第十三章:typedef 使用的陷阱,了解C++基本语言特性变量和类型

  首先来看typedef 和宏混用陷阱。为了说明这一问题,我们看下面这段代码:

#define PSTR MACRO char*     //定义一个宏类型PSTRMACRO
typedef char *PSTR;          //通过typedef定义一个新类型PSTR
int main(int argc, char* argv[])
{
  //声明两个变量piVar1和 piVar2
  PSTR piVar1, piVar2;
  //声明两个变量 piVar3和 piVar4
  PSTR_MACRO piVar3, piVar4;

  Inti   Var=100;           //定义一个int变量iVar

//将iVar变量地址赋给piVar1、piVar2、piVar3、piVar4四个变量
  piVar1 =&iVar;
  piVar2=&iVar;
  piVar3 =&iVar;
  piVar4 = &iVar;

  //输出 piVar1、piVar2,到 piVar3、piVar4 四个变量的值
  printf("piVar1=%0X\r\n",piVar1);
  printf("piVar2=%0X\r\n",piVar2);
  printf("piVar3 =%0X \r\n",piVar3);
  printf("piVar4=%0X \r\n",piVar4);
  returm 0:
}
  代码段的输出为:
  piVar1 =19FC78
  piVar2 =19FC78
  piVar3 =19FC78
  piVar4=78

  通过代码片段的执行结果可以看出typedef 和#define 还是有很大区别的。我们先分析一下为什么上述代码中4个变量的输出值不同。

  PSTRMACRO 为预处理宏,只是简单的字符串替换,piVar3 和 piVar4 经过预处理后,“PSTR_MACRO piVar3, piVar4;”声明转化为“char* piVar3, piVar4;”。到这里也许你已经看出问题来了:piVar4 是一个char 型变量,而不是 char*型变量。

  PSTR为一个通过typedef 定义的类型别名,不进行原地扩展,新定义的别名有一定的封装性。“PSTRpiVar1,piVar2;”在编译过程中,由于 PSTR 为 int 的别名,编译器会把“PSTR piVar1, piVar2;”语句当作“char *piVar1,*piVar2;”处理,而不是简单的宏替换。

  宏和typedef 的区别:

  ● 宏定义只是简单的字符串替换。

  ● typedef 定义的类型是类型的别名,typedef 后面是一个整体声明,是不能分割的一个整体,具有一定的封装性,不是简单的字符串替换。

  通过typedef 声明多个指针对象,形式直观,方便省事。例如声明3 个指针变量:

  char*pszA,*pszB,*pszC;              //声明3个指针变量,方式1

  typedef char*PSTR:                  //声明3个指针变量,方式2:直观省事
  PSTR   pszA, pszB, pszC;

  小心陷阱

  typedef 主要为复杂的声明定义简单的别名,它本身是一种存储类的关键字,与auto、extern、mutable、static、register 等关键字不能出现在同一个表达式中,如“typedefstatic int S_INT;”就是非法的。

  讨论了 typedef 和#define 的区别,我们继续讨论 typedef 的其他用途。

  (1) 用在旧的C代码中,声明struct新对象时,必须带上 struct,即形式为 struct结构名对象名,例如:

struct tagPOINT   //点数据结构
{
  Int x:
  Int y;
};
struct tagPOINT p1:

  为了实现在结构体使用过程中少写声明头部分的 struct,可采用如下实现方式:

typedef struct tagPOINT
{
  Int x;
  int y;
}POINT;
POINTp1;

  这样就比原来的方式少写了一个 struct,比较省事,尤其是在大量使用的时候。而在C++中则可以直接写:结构名对象名,即:

tagPOINT1 p1;

  在C++中,typedef 的这种用途就不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到以前遗留下来的代码。  

  (2) typedef 另外一个重要的用途就是定义与机器无关的类型,保障代码具有较好的跨平台特性。例如,可定义一个名为 REAL_NUM 的浮点类型,在目标机器上它可以获得最高的精度:

typedef long double REAL NUM;//实数

  在不支持 long double的机器上,通过typedef 可采用如下定义:

typedef double REAL_NUM;

  对于连 double 都不支持的机器上,通过typedef 可采用如下定义:

typedef float REAL_NUM;

  采用typedef 实现数据类型的定义,不用对源代码做任何修改,便可以在每一种平台上编译这个使用 REAL_NUM 类型的应用程序。

  唯一需要修改的是typedef 本身。在大多数情况下,甚至这个微小的变动完全都可以通过奇妙的条件编译来自动实现。不是吗?STL 标准库广泛地使用typedef 来创建这样的平台无关类型,size_t、ptrdiff 和 fpos_t 就是这样的例子。

  (3) 为复杂的声明定义一个简单的名称,简化代码。这一功能可增强代码的可读性和标识符的灵活性。我们看下面这个复杂的声明。在这个声明中,paFunc 为变量名称。

int *(*paFunc[6])(char *pszInput);

  现在看通过typedef 简化后的声明形式。

Typedef int*(*pFunc)(char*pszInput);
pFunc paFunc[6]

  最后,看一下 C++类经常使用的回调函数实现。假设有一个类叫隧道 CTunnel类,同时若此类接收到某一个数据时,回调一个预先设置好的回调函数。

//Tunnel.h 隧道类声明文件
//回调函数声明
typedef BOOL*CallBackFunc(const char*pszData, const int nDatalength);

//隧道类声明
class CTunnel
{
    CTunnel();
    virtual~CTunnel();
    //设置回调函数
    void SetCallBack(CallBackFunc *pCallBackFunc);
    //隧道接收数据处理函数
    int OnRcvData(const char *pszData, const int nDataLength);
private:
    //回调函数存储指针
    CallBackFunc m pCallBackFunc;
};
//Tunnel.cpp 隧道类实现文件
CTunnel::CTunnel()
{
m pCallBackFunc =NULL;
}
CTunnel::~CTunnel()
{
}
//设置回调函数
void CTunnel::SetCallBack(CallBackFunc *pCallBackFunc)
{
    m pCallBackFunc = pCallBackFunc
}
//隧道接收数据处理函数
int CTunnel::OnRcvData(const char *pszData, const int nDataLength)
{
if((NULL=pszData)|l(0 =nDataLength))
{
retum-1;
        }
        ...

    if(NULL !=m_pCallBackFunc
    {
      retum m_pCallBackFunc(pszData, nDataLength);
    }
    retum 0;
}
  请谨记
  ● 区分宏和 typedef 的差异,不要用宏的思维方式对待typedef,因为 typedef 声明的新名称具有一定的封装性,而#define 宏只是简单的字符替换。
  ● 尽量用typedef 实现那些复杂的声明形式,以保证代码清晰、易于阅读。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

常见问题

  • 如何安装和激活?

    每款软件会附带有安装教程,您打开安装包一目了然

  • 程序是否已损坏?文件损坏?还是其他错误?

    有错误问题,请您参考:https://www.xxx.com/error

  • 如何更新?正式激活后会发生什么情况?

    除非安装说明中另有说明,否则官方更新可能会导致无法激活。 要从本网站更新软件,您需要在此处下载此软件的新版本(如果可用),并将其安装在计算机上安装的版本之上(替换)。在这种情况下,您将保存此软件的激活和设置。

  • 如何下载?链接不起作用?

    我们使用百度网盘,132云盘和微软网盘,除了百度网盘,其他两款不限速,如果链接失效,请您联系客服处理

  • 已发布更新。我什么时候升级我的版本?

    所有软件如有更新,我们第一时间推送,视自己情况更新使用

  • 如何更改语言?

    打开“系统偏好设置”->“通用>语言和地区”->应用程序-“+”。 选择应用和语言。此方法适用于大多数应用程序。 Adobe 产品中的语言通常是在产品本身的安装阶段选择的。 游戏中的语言通常会在游戏本身的设置中发生变化。

  • 如何删除软件?

    有很多选择。最简单的方法是使用特殊的实用程序来卸载应用程序,例如App Cleaner Uninstaller 要删除 Adobe 产品,请使用 Creative Cloud Cleaner Tool

  • 需要远程帮助吗?

    网站已开通永久会员的可享受免费远程,如果非永久会员,远程安装另外收费

给TA打赏
共{{data.count}}人
人已打赏
技术教程

九大关键点揭秘,轻松掌握系统技术教程

2024-2-22 9:16:00

技术教程

第十四章:优化结构体中元素的布局,了解C++基本语言特性变量和类型

2024-2-23 10:27:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧