[C++基础编程]----预处理指令简介、typedef关键字和#define预处理指令之间的区别

目录

引言         

正文         

01-预处理指令简介        

02-typedef关键字简介        

03-#define预处理指令简介        

04-#define预处理指令和typedef关键字的区别        

(1)原理不同

(2)功能不同

(3)作用域不同

(4)对指针的操作不同

总结         


引言         

        在C++中,预处理指令是在编译程序之前由预处理器处理的特殊指令。它们以井号(#)开头,用于在编译代码之前执行一些文本替换和条件编译。预处理指令不是真正的C++代码,而是在编译器之前进行处理的指令。

        以下是几个常用的预处理指令:

        a、#include: 用于包含头文件。例如,#include <iostream> 会在编译时将iostream文件的内容包含到当前文件中。

        b、#define: 用于定义符号常量。例如,#define PI 3.14159 可以定义一个名为PI的符号常量,它的值为3.14159。

        c、#ifdef, #ifndef, #endif: 这些指令用于条件编译。例如,#ifdef DEBUG 可以检查是否定义了DEBUG符号常量,如果定义了,则编译下面的代码块。

        d、#if, #elif, #else: 用于条件编译,类似于C++中的if语句。例如,#if X > Y 编译器会检查X是否大于Y,如果是,则编译下面的代码块。

        e、#error: 用于在预处理阶段生成编译错误。例如,#error “Unsupported platform” 会生成一个编译错误,指示编译器不支持当前平台。

正文         

01-预处理指令简介        

        (1)#include        

        当使用 #include 预处理指令时,是在告诉编译器在编译当前文件之前将指定的头文件内容包含进来。这是一种非常常见的方式,用来在代码中引入其他文件中定义的函数、变量、类等内容,以便在当前文件中使用它们,从而实现代码的模块化和复用。

        下面是一个具体的示例:假设有一个名为 main.cpp 的文件,这个文件中使用 iostream 头文件中定义的 cout 对象,以便能够在控制台输出信息。

        在这个示例中,#include <iostream> 将 iostream 头文件的内容包含到了 main.cpp 文件中。因此,你可以在 main.cpp 中直接使用 std::cout,而不需要重新定义它。这样做的好处是,可以在多个文件中共享同一个头文件中定义的内容,避免了重复编写相同的代码,提高了代码的可维护性和可重用性。

// main.cpp
#include <iostream> // 包含iostream头文件

int main() {
    std::cout << "Hello, world!" << std::endl; // 使用iostream中的cout对象输出信息
    return 0;
}

        (2)#ifdef, #ifndef, #endif       

        #ifdef: 当定义了某个符号常量时,就会执行后面的代码。如果未定义该符号常量,则忽略后面的代码。下面是一个示例:

        在这个示例中,由于定义了DEBUG符号常量,因此输出"Debug mode is enabled"。如果注释掉#define DEBUG这行,那么#ifdef DEBUG中的代码就会被忽略。

#define DEBUG // 定义DEBUG符号常量

#ifdef DEBUG
    std::cout << "Debug mode is enabled" << std::endl;
#endif

  #ifndef: 与#ifdef相反,当未定义某个符号常量时,才会执行后面的代码。如果已定义了该符号常量,则忽略后面的代码。示例如下:

        在这个示例中,由于RELEASE未被定义,因此输出"Not in release mode"。

#ifndef RELEASE // RELEASE未定义
    std::cout << "Not in release mode" << std::endl;
#endif

  #endif: 用于结束#ifdef#ifndef的条件编译区域。示例如下:

        在这个示例中,如果定义了DEBUG则输出"Debug mode is enabled",否则输出"Debug mode is disabled"。

#ifdef DEBUG
    std::cout << "Debug mode is enabled" << std::endl;
#else
    std::cout << "Debug mode is disabled" << std::endl;
#endif

      (3)#if, #elif, #else       

        在C++中,#if#elif 和 #else 是条件编译的预处理指令,与 #ifdef#ifndef 和 #endif 类似,用于根据指定的条件来选择性地编译代码段。下面是它们的详细说明和代码示例:

  #if: 根据给定的条件进行条件编译。如果条件为真,则编译后面的代码;否则,忽略后面的代码。示例如下:

        在这个示例中,如果 DEBUG_LEVEL 的值大于1,则输出"Debugging level is high"。如果 DEBUG_LEVEL 不大于1,那么这段代码就会被忽略。

#if DEBUG_LEVEL > 1
    std::cout << "Debugging level is high" << std::endl;
#endif

   #elif: 用于在多个条件之间进行选择,相当于 “else if”。示例如下:

        在这个示例中,如果 DEBUG_LEVEL 的值为2,则输出"Debugging level is medium";如果 DEBUG_LEVEL 的值为1,则输出"Debugging level is low";否则输出"Debugging level is off"。

#if DEBUG_LEVEL == 2
    std::cout << "Debugging level is medium" << std::endl;
#elif DEBUG_LEVEL == 1
    std::cout << "Debugging level is low" << std::endl;
#else
    std::cout << "Debugging level is off" << std::endl;
#endif

   #else: 用于在前面的条件都不满足时执行的代码。示例如下:

        在这个示例中,如果定义了DEBUG符号常量,则输出"Debug mode is enabled";否则输出"Debug mode is disabled"。

#if defined(DEBUG)
    std::cout << "Debug mode is enabled" << std::endl;
#else
    std::cout << "Debug mode is disabled" << std::endl;
#endif

      (4)#error     

        #error 预处理指令在 C++ 中用于产生编译错误,并显示指定的错误消息。这个指令通常用于在编译时检测到某些条件不满足时,中断编译过程并输出错误信息,以提示开发者进行修复。

        下面是详细的说明和代码示例:在这个示例中,如果 DEBUG 符号常量被定义,编译过程将中断,并显示错误消息"Debug mode is enabled. Disable debug mode before compiling for release."。这可以帮助确保在发布版本中不会意外地包含调试相关的内容或功能。

#if defined(DEBUG)
    // 如果定义了DEBUG符号常量,则编译出错并显示错误消息
    #error Debug mode is enabled. Disable debug mode before compiling for release.
#endif

02-typedef关键字简介        

        typedef 是一个关键字,而不是预处理指令。它用于为已有的类型取一个新的名字,使得代码更易读并且更具可移植性。

        下面是详细的说明和代码示例:在这个示例中,typedef 关键字用于为 int 类型取一个新的名字 Integer,从而在代码中可以用 Integer 代替 int。这样代码看起来更清晰,并且如果需要修改数据类型时,只需在 typedef 的地方进行修改,而不必在所有代码中逐一修改。

typedef int Integer; // 将"int"类型取一个别名为"Integer"

Integer x = 10; // 定义一个整型变量x,并赋值为10

// 使用新定义的别名Integer
void printInteger(Integer num) {
    std::cout << "The integer is: " << num << std::endl;
}

printInteger(x); // 调用函数打印变量x的值

03-#define预处理指令简介        

        #define 是C++中用于创建宏的预处理指令。它允许您定义一个带有名称的常量或者带有参数的函数样式宏。宏定义会在编译之前进行文本替换。

        下面是详细的说明和代码示例:

        (1)定义常量:

#define PI 3.14159

// 使用宏定义的常量
double circleArea(double radius) {
    return PI * radius * radius;
}

        在这个示例中,#define PI 3.14159 定义了一个名为 PI 的常量,它代表圆周率。在函数 circleArea 中,可以直接使用 PI 来计算圆的面积。

        (2)定义带参数的宏:

#define SQUARE(x) ((x) * (x))

// 使用带参数的宏
int main() {
    int result = SQUARE(5);
    std::cout << "Square of 5 is: " << result << std::endl; // 输出 25
    return 0;
}

        在这个示例中,#define SQUARE(x) ((x) * (x)) 定义了一个名为 SQUARE 的宏,它接受一个参数 x,并返回 x 的平方。在 main 函数中,SQUARE(5) 将被替换为 (5) * (5),最终计算出结果为 25。

        注:使用 #define 宏可以简化代码、提高可读性,但要注意它们的一些潜在问题,比如可能引发意外的副作用,因为它只是简单的文本替换。

04-#define预处理指令和typedef关键字的区别        

        #define预处理指令和typedef关键字的区别如下:

      (1)原理不同

  #define 预处理指令: #define 实质上是一个简单的文本替换机制。它在预处理阶段将指定的文本字符串替换为另一个字符串或表达式。

        这段代码将在预处理阶段将所有出现的 PI 替换为 3.14159

#define PI 3.14159

  typedef 关键字: typedef 是用于为数据类型定义一个新的名称,它在编译器层面上为给定的数据类型创建一个别名。

        这段代码在编译器层面为 int 类型创建了一个别名 Integer

typedef int Integer;

     (2)功能不同

  #define 预处理指令: 主要用于创建宏,可以用来定义常量、函数样式宏等。它提供了一种简单的文本替换机制,可以用于代码中的任何地方。

        这个示例定义了一个常量 MAX_SIZE,用于表示数组的最大大小。

#define MAX_SIZE 100

  typedef 关键字: 用于为已有的数据类型创建一个新的名称,使代码更易读并增加可移植性。它允许在代码中引入自定义的类型名称,以增强代码的可读性和可维护性。

        这个示例创建了一个别名 Integer,用于表示 int 类型。

typedef int Integer;

    (3)作用域不同

  #define 预处理指令: 宏定义的作用域是全局的,即从定义处到文件结束或另一条取消宏定义的指令为止。

        该宏定义的作用域是全局的,从定义处到文件结束或另一条取消宏定义的指令为止。

#define MAX_SIZE 100

  typedef 关键字: 类型别名的作用域是局部的,它只在定义它的作用域内有效。

        类型别名的作用域是局部的,只在定义它的作用域内有效。

typedef int Integer;

    (4)对指针的操作不同

  #define 预处理指令: #define 可以用来创建函数样式宏,包括指针操作。但它只是简单的文本替换,可能会导致一些不直观的行为。

        这段代码创建了一个指针类型的宏定义 PTR_INT,它可能引发一些不直观的行为。

#define PTR_INT int*

  typedef 关键字: typedef 可以创建指针类型的别名,使得对指针更加清晰易懂。通过 typedef 可以创建更具有语义的指针类型,增强代码的可读性。

        这段代码创建了一个指针类型的别名 IntPtr,使得指针类型更加清晰易懂。

typedef int* IntPtr;

        下面这个示例中,#define 定义了一个常量 MAX_SIZE 和一个交换两个数值的函数样式宏 SWAP。而 typedef 则定义了两个类型别名 Integer 和 IntPtr,分别表示整数和整型指针。

// #define 示例
#define MAX_SIZE 100

// 定义函数样式宏,交换两个数值
#define SWAP(x, y) { int temp = x; x = y; y = temp; }

// typedef 示例
typedef int Integer; // 将int类型取别名为Integer
typedef int* IntPtr; // 将int指针类型取别名为IntPtr

int main() {
    // #define 示例
    int arr[MAX_SIZE]; // 使用常量定义数组大小

    int a = 5, b = 10;
    SWAP(a, b); // 使用函数样式宏交换a和b的值

    // typedef 示例
    Integer num = 100; // 使用别名Integer定义变量
    IntPtr ptr = &num; // 使用别名IntPtr定义指针变量

    return 0;
}

总结         

       预处理指令在C++中可以用来控制编译过程、优化代码、进行平台适配等,是编写高效、可维护程序的重要工具之一。但是过度使用预处理指令可能会导致代码复杂难懂,因此在使用时需要谨慎并遵循良好的编程实践。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【YOLOv8改进[Backbone]】使用SCINet改进YOLOv8在黑暗环境的目标检测效果

目录 一 SCINet 1 本文方法 ① 权重共享的照明学习 ② 自校准模块 ③ 无监督训练损失 二 使用SCINet助力YOLOv8在黑暗环境的目标检测效果 1 整体修改 2 配置文件 3 训练 其他 一 SCINet 官方论文地址&#xff1a;https://arxiv.org/pdf/2204.10137 官方代码地址&…

26_Scala集合常用API汇总

文章目录 1.mkString2.size&#xff0c;length&#xff0c;isEmpty,contains3.reverse ,length,distinct4.获取数据相关4.1数据准备4.2准确获取尾部last4.3 除了最后一个元素不要其他都要4.4从集合获取部分数据 5.删除数据5.1删除3个从左边5.2删除3个右边 6.切分数据splitAt(n:…

解决“您的连接不是私密连接”

目录 那么为什么会出现这样提示呢 https访问有什么不同 将http访问更改为https访问 当您在浏览网页时&#xff0c;遇到“您的连接不是私密连接”的提示&#xff0c;这通常表示浏览器认为您的连接不够安全。这是因为浏览器无法信任网站使用的SSL证书&#xff0c;或者网站没有…

【系统架构师】-UML-用例图(Use Case)

1、概述 用于表示系统功能需求&#xff0c;以及应用程序与用户或者与其他应用程序之间的交互关系。 2、组成 参与者&#xff08;Actors&#xff09;&#xff1a;与系统交互的用户或其他系统。用一个人形图标表示。用例&#xff08;Use Cases&#xff09;&#xff1a;系统需要…

平滑矢量图形综述:表示、创建、光栅化和图像矢量化的最新进展

摘要 平滑矢量图形领域探索了轻量级图像表示的表示、创建、光栅化和自动生成&#xff0c;常用于可缩放图像内容。过去几十年中&#xff0c;出现了多种概念性方法来表示具有平滑渐变的图像&#xff0c;每种方法都引发了独立的研究线索&#xff0c;包括流行的梯度网格和扩散曲线…

工程技术SCI期刊,中科院三区,一投就中,国人友刊!

一、期刊名称 Industrial Management & Data Systems 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;工程技术 影响因子&#xff1a;5.5 中科院分区&#xff1a;3区 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;$4120 三、期刊征稿范…

QT功能 实现静态内容国际化实验

文章目录 第一步&#xff1a;新建一个QT工程第二步&#xff1a;添加控件第三步&#xff1a;在pro文件中添加内容第四步&#xff1a;更新文件第五步&#xff1a;打开QT的Linguist第六步&#xff1a;添加翻译内容第七步&#xff1a;回到QT Creator中添加文件第八步&#xff1a;给…

Colibri for Mac v2.2.0激活版:专业级无损音乐播放器

Colibri for Mac是一款专为Mac用户设计的高分辨率无损音乐播放器。它基于BASS技术构建&#xff0c;为用户带来极致的音频体验。Colibri支持所有流行的无损和有损音频格式&#xff0c;如FLAC、MP3、AAC等&#xff0c;确保音乐播放的清晰度和完美度。其独特的清晰比特完美播放技术…

月均互动超50万!“仪式感”何以盛行?小红书数据分析揭示消费动力

现代年轻人&#xff1a;“赚不到钱&#xff0c;却爱花钱买仪式感”。审慎消费的当下&#xff0c;“仪式感消费”不减反增&#xff0c;小红书平台相关内容更是持续火爆&#xff0c;成为品牌圈粉消费者的关键词。 这届小红书用户&#xff0c;热衷为“仪式感”氪金 “XX的第一杯奶…

【mysql】mysql单表查询、多表查询、分组查询、子查询等案例详细解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

常用的外贸软件有哪些

常用的外贸软件涵盖了多个方面&#xff0c;包括客户开发、订单管理、库存控制、客户关系管理(CRM)、财务管理以及跨境电商平台等。以下是一些代表性的外贸软件和平台&#xff1a; 客户开发与营销软件: 大镜山谷歌搜索大师易谷歌地图数据采集大师米贸搜 外贸管理软件 (ERP): 神卓…

【Kali Linux工具篇】使用Aircrack-ng破解wifi密码

前期准备 1、一个无线网卡 2、密钥爆破字典 实站过程 1、设置wlan为监听模式 airmon-ng start wlan0 #开启网卡wlan0监听模式 iwconfig #查看网卡状态&#xff0c;发现wlan0mon&#xff0c;表示已开启成功2、探测附近WiFi airdump-ng wlan0monBSSID 代表…

零售全渠道营销业务链分析,让企业管控能力大幅加强!

对于传统的、规模化的零售快消企业来讲&#xff0c;面临着很大的渠道管理和建设问题&#xff0c;如何尽快实现整个营销体系的全渠道数字化转型是当务之急、重中之重。 面对错综分散的经销商&#xff0c;零售快消企业订货流程会越复杂&#xff0c;加之对门店管理较为粗放&#…

技术速递|Java on VS Code 3月更新 - 大量 Spring 新功能!测试覆盖率功能正式发布!​

作者&#xff1a;Nick Zhu 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎来到2024年3月的 Visual Studio Code Java 更新&#xff01;在本篇博客中&#xff0c;我们将分享大量 Spring 有关的新功能以及测试覆盖率的更新&#xff0c;让我们开始吧&#xff01; Spring Boot…

【网络】网络层ICMP协议

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&am…

新建的springBoot WEB项目无法自动返回html模版(gradle+kotlin版本)

最近研究了springBoot创建web项目&#xff0c; 第一步服务端返回字符串没有问题&#xff0c;第二步返回html时&#xff0c;还是返回的字符串。 文章目录 一、参考方案二、新建springBoot web项目三、启动项目的三种方式 一、参考方案 将控制器类的 RestController 改为 Contro…

【JavaWeb】网上蛋糕商城后台-订单管理

概念 前面通过多篇文章以完全实现了用户在网上蛋糕商城平台上的所有功能和操作&#xff0c;从本文开始&#xff0c;实现网站的后台管理功能的介绍和操作。 订单列表 想要进入后台管理系统&#xff0c;则登入的用户一定是管理员账号&#xff0c;这个账号和密码只有管理员才知…

图搜索算法 - 拓扑排序

相关文章&#xff1a; 数据结构–图的概念 图搜索算法 - 深度优先搜索法&#xff08;DFS&#xff09; 图搜索算法 - 广度优先搜索法&#xff08;BFS&#xff09; 拓扑排序 概念 几乎所有的工程都可分为若干个称作活动的子工程&#xff0c;而这些子工程之间&#xff0c;通常受…

多个开源的js补环境框架测试

原文链接&#xff1a;https://mp.weixin.qq.com/s/uEMFGpE5bqmTvzSgX2twvA 前言 在做js逆向时肯定会遇到补环境的情况&#xff0c;看到github开源了好几个补环境用的框架&#xff0c;这篇文章做个测试&#xff0c;看看哪个比较好用。 https://github.com/pysunday/sdenvhttp…

使用Tkinter实现数据预测工具的GUI界面展示

如果构建好预测模型后&#xff0c;想将预测模型通过一个交互式的页面显示&#xff0c;可以通过下边两种方式实现。 本文中代码有详细解析注释&#xff0c;便不再如往期一样分开讲解了&#xff0c;有需要的朋友可以直接拿去使用&#xff0c;代码可以直接运行&#xff0c;把预测…