#define、typedef 和 using之间的联系和区别

2023-05-16

目录

一 、#define

1. 含义

2. 用处

1. 条件编译

2. 解宏

3. 文件包含

二 typedef

1. 含义

2. 用处

1. 数据类型别名

2. 指针别名

3. 结构体别名

4. 与平台无关的数据类型

三 using

1. 含义        

2. 用处

1. 权限管理

2.类型重命名

3. 继承体系中,改变部分接口函数的继承权限

四 #define和typedef的区别


一 、#define

1. 含义

        #define主要用来做宏定义,主要格式为:

#define 标识符 常量

        宏定义后的标识符就是代表常量的意思,再以后的代码当中,使用标识符的地方都被替换成常量了,这里的常量可以是字符、字符串、变量、类型、表达式等等。值得注意的是,宏定义定义的标识符是在程序编译之前的预处理阶段进行替换的,也就是说在预处理阶段,已经把程序中所有的标识符全部替换成了常量,因此在程序运行阶段是调试不了该标识符的。

2. 用处

1. 条件编译

        所谓条件编译就是宏开关,当多个厂家找你开发一套程序,而这一套程序的逻辑恰好一样的,只是有些地方需要有不同的显示,你会选择统是开发多个项目吗,这是一个很蠢的做法,因为这几套程序的代码90%是相同的,你同时维护这么多套程序会很占用你的内存资源的,所以这个时候宏开关(条件编译)就起到了很好的作用,它相当于在你的程序开头定义一个宏变量,然后在你需要转换不同厂家不同逻辑代码的地方进行判断就可以了。

#include<iostream>
using namespace std;

# define GOOGLE 0
# define FACEBOOK 1



void main(){
    string result = "0";

#ifdef GOOGLE
    result = "I am a google company!";
#endif
#if FACEBOOK
    result = "I am a facebook company!";
#endif


    cout<<result;

}

当GOOGLE = 0时,打印的结果是GOOGLE:

 当FACEBOOK = 0时,打印的结果是FACEBOOK:

 

2. 解宏

#define宏定义的变量的作用域是整个程序,当然,你也可以通过#undef来解宏,就是在解宏后,解宏后面代码中的这个宏定义标识符就失效了。

#include<iostream>
using namespace std;

# define GOOGLE 0
# define FACEBOOK 1



void main(){
#ifdef GOOGLE
    result = "I am a google company!";
#endif



#if FACEBOOK
    result = "I am a facebook company!";
#endif

#undef FACEBOOK                                    // 解宏

#ifdef FACEBOOK                                    // 失效
    result = "I am a facebook company!";
#endif

    cout<<result;
}

我们可以看一下在解宏FACEBOOK后编译器的界面显示,QT界面上显示了解宏后再去判断宏的话是没有起到效果的:

3. 文件包含

宏定义还可以避免我们在开发程序时头文件相互引用,这样做的好处就是减少编译器的工作量

#ifndef _HEADFILE_
#define _HEADFILE_

...

#endif

先判断有没有包含头文件_HEADFILE_,如果没有的话就引入,例如在Test.h文件中

#ifndef TEST_H
#define TEST_H

...

#endif // TEST_H

二 typedef

1. 含义

        用typedef来给类型起一个别名,主要格式为:

typedef 类型 别名

类型可以是基本数据类型,也可以是结构体等等。

2. 用处

1. 数据类型别名

        定义了一个类型符号INT_32,用来表示int数据类型,在接下来的变量定义中可以使用该别名INT_32进行操作;

typedef int INT_32;

INT_32 A = 9;

2. 指针别名

        定义了一个类型符号PCHAR,表示char指针,用PCHAR来定义Serven_3和Serven_4就可以让Serven_3 和 Serven_4成为char类型指针。

typedef char* PCHAR;

char Serven_1 = 's';
char Serven_2[] = "123456";

PCHAR Serven_3, Serven_4;


Serven_3 = &Serven_1;            // 指向Serven_1
Serven_4 = &Serven_2;            // 指向Serven_2

        值得注意的是   PCHAR Serven_3, Serven_4  等价于  char *Serven_3, *Serven_4  ,它跟  char *Serven_3, Serven_4  不一样,前者是两个char类型的指针,后者是一个char类型指针,一个char类型变量。

        在Serven_3前面加上const,会变成一个指针常量,指向的变量地址不能修改,但可以通过执政去修改变量的值。

const PCHAR Serven_5;

3. 结构体别名

        以往定义一个结构体如下所示

struct Student{
    int StuNo;
    char StuName[20];
};

        如果我们需要实例化结构体对象,那么操作是:

struct Student Ser_stu;        // 实例化一个结构体变量

        现在我们可以通过typedef来给结构体一个别名

typedef struct Student{
    int StuNo;
    char StuName[20];
}Stu;

        这下我们来实例化结构体对象的操作可以为:

Stu Ser_stu;            // 实例化一个结构体变量

4. 与平台无关的数据类型

        在日常开发中,特别是在嵌入式单片机的开发中,我们可以通过定义一些平台没有提供的数据类型,例如:

typedef unsigned char BYTE;              // 别名一个BYTE类型
typedef unsigned int UINT_32;            // 别名一个32长度的整型类型

三 using

1. 含义        

        using的作用是给数据类型起别名,它的作用跟typedef相似,主要格式为:

using 别名 = 类型等

2. 用处

1. 权限管理

        配合命名空间,对命名空间权限进行管理

using namespace std;                // 释放整个命名空间到当前作用域
using::string;                      // 释放某个变量当前作用域

        我相信你在刚开始接触C/C++语言的时候都会遇到过下面的代码,即没有加上命名空间权限using namespace std; 这会导致main函数中string是无法标识的,解决方案有两个,要么加上整个命名空间权限,要么在string前面加上std::。

#include<iostream>

void main(){
    string serven;
}

2.类型重命名

        给string类型起一个别名,这样的格式看起来比typedef更加直观吧。

using Dstring = std::string;

        可以给一个很长的类名起一个别名:

using ILV = I_LOVE_YOU;

3. 继承体系中,改变部分接口函数的继承权限

        当我们在面向对象编程的时候,往往会继承别的类,继承有三种方式,分别是公有继承(public)、私有继承(private)、保护继承(protected)。在这三种继承中,私有继承后,父类的所有成员属性和方法都成为了派生类的私有成员,这会导致派生类实例化的对象是不能访问这些成员属性和方法的,在这个时候,using就起到作用了,使用using就可以将其变成公有成员

class Parents{
    Parents(){}
    ~Parents(){}
public:
    int serven1;
public:
    int Speak(){
    cout<<"I am taking!";    
    }

};



class Child(): private Parents{
public:
    using Parents::Speak();

}



void main(){

    Child Serven2 = new Child();
    Serven2.Speak();                        // 可以调用,因为使用了using,并且在子类中的public        
    Serven2.serven1;                        // 不能调用,因为是私有属性
}

四 #define和typedef的区别

        我们只看它们的第一个无别,typedef的别名前面加上const后表示定义的变量为指针常量,而define定义的表示常量指针。

#include<iostream>
using namespace std;

typedef int* PINT;
#define pint int*


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    const PINT serv1;               // 相当于指针常量
    PINT serv1;
    const pint serv2;               // 相当于常量指针

    int s = 7;
    int d = 3;

    serv1 = &s;
    serv2 = &s;

    cout<<*serv1<<endl;
    cout<<*serv2<<endl;

    serv1 = &d;                    // 出错,因为指针常量不能指向别的变量地址了
    serv2 = &d;

    cout<<*serv1<<endl;
    cout<<*serv2<<endl;


    *serv1 = 6;
    //*serv2 = 6;                  // 出错,因为常量指针不能修改变量的值

    cout<<*serv1<<endl;
    cout<<*serv2<<endl;



    PINT SERVEN1, SERVEN2;          // 表示SERVRN1和SERVEN2两个都是指针变量
    SERVEN1 = &d;
    SERVEN2 = &d;

    pint SERVEN3, SERVEN4;          // 只是做简单的替换,SERVEN3是指针变量,SERVEN4是int变量
    SERVEN3 = &d;
    SERVEN4 = 9;


    cout<<*SERVEN1<<endl;
    cout<<*SERVEN2<<endl;
    cout<<*SERVEN3<<endl;
    cout<<SERVEN4<<endl;

    return a.exec();
}

运行结果:

另外一个区别就是:

1. typedef是一个语句,后面要加上分号

2. #define是一个关键字,只是在做标识符的替换

3. typedef是在运行期间进行的,#define是在预编译期间进行的。

4. typedef在语法上是一个存储类的关键字(如auto、extern、mutable、static、register等一样),虽然它并不真正影响对象的存储特性,如:

typedef static int INT2; //不可行

   编译将失败,会提示“指定了一个以上的存储类”。

5. 在有指针的情况下,typedef会好一些,因为下面代码中,PCHARdef仅仅是做字符串的替换,所以SERVEN3是一个指针,而SERVEN4是一个char类型的变量。PCHARtyp定义的两个SERVEN1和SERVEN2都是插入指针。

typedef char* PCHARtyp;
#define PCHARdef char*


PCHARtyp SERVEN1, SERVEN2;
PCHARdef SERVEN3, SERVEN4;

喜欢就给小编点个赞吧,欢迎关注微信公众号 “三贝勒文子

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

#define、typedef 和 using之间的联系和区别 的相关文章

  • 令人困惑的 typedef 涉及类作用域

    我正在阅读 C 项目的代码 它包含以下形式的一些代码 namespace ns class A class B struct C typedef ns A ns B type 有人可以解释一下它的含义吗typedef line type似乎
  • 如果我在 C 或 C++ 中执行“typedef”,什么时候应该在 typedef 类型的末尾添加“_t”? [复制]

    这个问题在这里已经有答案了 我很困惑什么时候应该添加尾随 t to typedef ed 类型 例如 我应该这样做 typedef struct image image t or this typedef struct image imag
  • 如何在 C 中创建 24 位无符号整数

    我正在开发一个 RAM 非常紧张的嵌入式应用程序 为此 我需要创建一个 24 位无符号整数数据类型 我正在使用一个结构来执行此操作 typedef struct uint32 t v 24 uint24 t 然而 当我询问这种类型的变量的大
  • C# 中集中使用关键字

    有没有办法在 C 中制作单个 头 类型文件 在 C 中 您有类似 Mainheader h 的内容 其中包含您的所有包含内容 有没有一种方法可以对 C 执行类似的操作 其中您有一个包含所有 using 关键字的文件 现在我有很多使用 例如
  • 使用内收益回报

    如果我没记错的话 当我在里面使用yield时using SqlConnection阻止我遇到运行时异常 using var connection new SqlConnection connectionString var command
  • 重新定义;不同的基本类型(typedef struct)

    当结构在不同的文件中定义时 我在尝试使结构正常工作时遇到了一些麻烦 据我所知 错误告诉我该结构被定义了两次不同的时间 我相信也许我可能需要在某个地方使用 extern 我尝试过尝试并在 Google 上寻求帮助 但没有成功 任何帮助将不胜感
  • C++ 中“使用命名空间 ::X”中的前导 :: 是什么意思

    有人可以解释一下以下命名空间用法之间的区别 using namespace layer module and using namespace layer module 是什么原因导致额外的 before layer 如果在以下上下文中使用它
  • 从 using() 语句内部返回有任何副作用吗?

    返回一个方法值inside获取 DataContext 的 using 语句似乎总是有效fine 像这样 public static Transaction GetMostRecentTransaction int singleId usi
  • C# using 语句捕获错误

    我只是查看 using 语句 我一直知道它的作用 但直到现在还没有尝试使用它 我想出了以下代码 using SqlCommand cmd new SqlCommand reportDataSource new SqlConnection S
  • C#“使用”块

    我有类似下面的代码 这里有人提到 WebClient Stream 和 StreamReader 对象都可以从使用块中受益 两个简单的问题 1 这个小片段在使用块时会是什么样子 我自己做研究没有问题 所以资源链接很好 但只看一个例子会更快更
  • C++ typedef 类的使用

    为什么要使用一个typedef class Name 我在IBM C 文档 http publib boulder ibm com infocenter comphelp v7v91 index jsp topic com ibm vacp
  • 多重使用块c#

    我正在开发需要访问数据库的应用程序 使用 using 语句很好 因为 using statement is to ensure that the object is always disposed correctly and it does
  • 在头文件中使用声明

    我一直在寻找有关使用的一些说明使用声明在头文件中 我正在四处搜索 但无法完全得到我正在寻找的答案 到目前为止我的研究得出的结论是 将它们用于非全局的范围是好的 而命名空间指令则不好 我明白 至少我希望如此 所以在我的例子中我使用shared
  • 关于C++类中typedef函数的疑问

    我需要定义一个返回类对象的函数 假设我有一个名为狗的类 h 中的类声明和 cpp 中的实现 当狗死时 我想调用一个函数让狗管理器知道这一点 在dog的SetFunc中我将收到要调用的函数 Dog h class Dog public typ
  • 如果没有“typedef”,如何创建在 C# 泛型中使用的相关类型组?

    作为一名 C 背景的人 我遇到过以下情况 鉴于 c 不支持 typedef 如何以编程方式关联类型 也就是说 在 C 中 我可以将相关类型存储为 typedef 以便在与模板一起使用时进行检索 在 C 中无法以同样的方式完成同样的事情 因为
  • 如何使用 Moq 返回数据或值列表?

    谁能告诉我如何使用 Moq 框架使用模拟对象返回数据列表并将返回的数据列表分配给另一个 List 变量 public class SomeClass public virtual List
  • C++ 模板 typedef

    我有课 template
  • 为什么迭代器类型推导失败? [复制]

    这个问题在这里已经有答案了 为什么这在 C 中不起作用 为什么我不能限制foo的参数为std vector
  • 将 CFIndex 转换为 NSUInteger?

    我如何转换typedef signed long CFIndex to typedef unsigned int NSUInteger 如果我使用一个可以吗 CFIndex作为类型的参数NSUInteger 我还没有铸造它 编译者似乎也不介
  • typedef 结构体指针定义

    我对 C 很陌生 并且对所有指针的东西都有一些问题 我写了这段代码 typedef struct edgeitem double weight EDGE ITEM pEDGE ITEM also declaration of a point

随机推荐

  • AJAX和CGI 技术的应用

    AJAX xff0c CGI 一 AJAX1 AJAX的概述AJAX局部更新网页流程图 xff1a 异步流程 xff1a 2 AJAX的通信过程2 1 创建xmlHttpRequest对象2 2 设置服务器响应的回调函数标准的XMLHttp
  • W25QXX使用教程

    W25QXX是华邦公司生产的一块FLASH储存芯片 那W25Q256为例 xff1a 驱动方式 xff1a 单路双路四路SPI QSPI xff1b 擦写周期 xff1a 10W次 支持电压 xff1a 2 7 3 6V 频率 xff1a
  • QT串口通信

    QT串口的使用 1 添加头文件2 串口通信的7个步骤3 发送接收数据 1 添加头文件 span class token macro property span class token directive keyword include sp
  • Qt存储图片到数据库&&从数据库读取图片

    使用Qt将图片存储到sqlite my sql span class token double colon punctuation span span class token function my sql span span class
  • SQL常用语句大全

    创建表and插入数据 课程表 span class token keyword create span span class token keyword database span stuinfo span class token comm
  • 2020-08-21 多路复用TCP双向通信

    多路复用TCP双向通信 首先说一下多路复用 多路的作用 xff1a 监测文件描述符的状态变化 监测文件描述符是否有数据可读写 状态变化 xff1a 有数据可读 xff0c 有数据可写 xff0c 异常 有可能需要监测多个文件描述符 多个文件
  • ros中gmapping建图

    准备 1之前在github上下载的双轮差速小车中有该小车的gmapping和键盘控制的文件可以直接用 2如果之前安装的不是ros的full版本还需要下载gmapping功能包 sudo apt get install ros indigo
  • ros导航仿真——定位与路径规划

    准备 之前在github上下载的差速双轮小车不仅有其对应的gmapping还有amcl和move base xff0c 其中amcl用于定位 xff0c move base 用于路径规划 首先启动小车 roslaunch diff whee
  • arm底层通讯接口之uart

    1 目的 写这篇博文的主要目的就是让其他初学者能够更快的理解 掌握uart串口通讯 xff0c 在学习底层接口通讯的时候 xff0c 我们要带着这么几个问题 xff1a 1 xff09 什么是uart 2 xff09 uart有什么用 3
  • ros中Odom话题与odom坐标系的理解

    odom话题发表的是odom坐标系到base link之间的转换关系 xff0c 以及机器人的速度 其中base like是机器人本体坐标系 xff0c 与机器人中心重合 xff0c 所以odom坐标系到base link之间的转换关系也就
  • 多机器人导航与编队(一)

    多个机器人中让领导者导航 xff0c 相比于单个机器人导航需要修改的参数如下 主要是多机器人中的领导者与单个机器人发布的话题名称不一样 小车启动文件设置与简化 1设置 在小车的xacro文件的diff插件中添加 span class tok
  • 多机器人导航与编队(二)

    小车导航文件设置 导航分为两部分 xff1a 定位amcl和规划move base xff08 我自己的项目 导航对应ares1 maze2 amcl launch里面包含ares1 amcl launch xml 对应定位amcl xff
  • 多个小车相同功能的节点编写以及launch文件相关设置

    对于n个小车的相同功能 xff0c 写cpp 1写n个cpp 2写1个cpp xff0c 将n个小车的内容集中到一起 3写1个cpp xff0c 长度与单个相同 在launch文件中启动n个这样相同的节点 传入n个不同的参数 关于launc
  • ROS 多机器人导航salm中的问题

    ros中slam理解 在ROS中 xff0c 进行导航需要使用到的三个包是 xff1a xff08 1 xff09 move base xff1a 根据参照的消息进行路径规划 xff0c 使移动机器人到达指定的位置 这个路径规划包括全局路径
  • 一文读懂串口(波形分析、起始位、数据位、停止位、空闲位)

    串口 一 串口 xff08 串行接口 xff09 二 异步串口 xff08 以下统称串口 xff09 三 重要参数1 波特率2 报文格式2 1 起始位2 2 数据位2 3 奇偶校验位2 4 停止位2 5 空闲位 四 波形1 具体连接2 波形
  • #学习笔记 keil环境下单片机模块化编程的方法

    1 选择 add new item to group 建立一个 c文件 xff0c 一个 h文件 xff0c 并且名字一致 2 h文件的写法 xff08 1 xff09 h文件中要有首位两段语言 例如 ifndef HEARTRATE H
  • 【Drone】航模遥控系统各协议简介

    最近学习了无人机的一些知识 xff0c 在关于遥控系统这部分的各种协议看的有些头大 xff0c 人都晕了 看了一些资料后终于大概理解了这套系统中那些一团乱麻般的各协议的意义 xff0c 大致总结一下 图一 遥控系统组成 这里参考FPV帮装机
  • C语言获取当前的工作路径

    在C语言中获取当前的工作路径的方法一般是用内置函数为 xff1a DWORD GetModuleFileName HMODULE hModule LPTSTR lpFilename DWORD nSize 函数的参数说明 xff1a hMo
  • C/C++的指针传递和引用传递

    相信你遇到过指针传参 值传参 引用传参 xff0c 这三个关系足够让你头脑爆炸 xff0c 搞不清楚三者的区别 但是恭喜你 xff0c 你看到了这篇文章 xff0c 小编保证你看后茅塞顿开 xff0c 一下子就顺畅了 首先 xff0c 我们
  • #define、typedef 和 using之间的联系和区别

    目录 一 define 1 含义 2 用处 1 条件编译 2 解宏 3 文件包含 二 typedef 1 含义 2 用处 1 数据类型别名 2 指针别名 3 结构体别名 4 与平台无关的数据类型 三 using 1 含义 2 用处 1 权限