[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 DEBUGstd::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 DEBUGstd::cout << "Debug mode is enabled" << std::endl;
#elsestd::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 > 1std::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 == 2std::cout << "Debugging level is medium" << std::endl;
#elif DEBUG_LEVEL == 1std::cout << "Debugging level is low" << std::endl;
#elsestd::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;
#elsestd::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; // 输出 25return 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指针类型取别名为IntPtrint 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++中可以用来控制编译过程、优化代码、进行平台适配等,是编写高效、可维护程序的重要工具之一。但是过度使用预处理指令可能会导致代码复杂难懂,因此在使用时需要谨慎并遵循良好的编程实践。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

IP协议全解析:网络层通信的基石

⭐小白苦学IT的博客主页⭐ ⭐初学者必看&#xff1a;Linux操作系统入门⭐ ⭐代码仓库&#xff1a;Linux代码仓库⭐ ❤关注我一起讨论和学习Linux系统❤ 前言 在数字化时代的浪潮中&#xff0c;网络通信无处不在&#xff0c;它连接着世界的每一个角落&#xff0c;承载着信息的高…

FileLink跨网文件交换的交换方式:满足不同场景下的文件交换需求

FileLink&#xff0c;作为一款创新的文件交换工具&#xff0c;不仅满足了用户在日常生活中对文件传输的需求&#xff0c;更在技术上实现了跨网文件交换的突破。其独特之处在于支持邮件方式投递、文件中转站、网盘模式共享三种交换方式&#xff0c;这使得FileLink能够适应不同场…

3D 交互展示该怎么做?

在博维数孪&#xff08;Bowell&#xff09;平台制作3D交互展示的流程相对简单&#xff0c;主要分为以下几个步骤&#xff1a; 1、准备3D模型&#xff1a;首先&#xff0c;你需要有一个3D模型。如果你有3D建模的经验&#xff0c;可以使用3ds Max或Blender等软件自行创建。如果没…

MySQL中的ON DUPLICATE KEY UPDATE和REPLACE

在 MySQL 中&#xff0c;ON DUPLICATE KEY UPDATE 和 REPLACE 语句都可以用来处理插入数据时主键或唯一键冲突的情况&#xff0c;但它们在处理冲突的方式上有所不同。它们有以下区别&#xff1a; 行为方式&#xff1a; ON DUPLICATE KEY UPDATE&#xff1a;当插入的数据行存在冲…

【智能安防监控补光灯调光芯片方案】单节锂电降压恒流驱动芯片FP8013 最大输出3A体积小/静态功耗低/效率高/支持无频闪调光

文章目录 文章目录 前言 一、pandas是什么&#xff1f; 二、使用步骤 1.引入库 2.读入数据 总结 前言 随着智能安防监控技术的不断发展&#xff0c;补光灯的关键性能也日益受到重视。为了提供更好的夜间监控效果&#xff0c;我们需要一种高效、稳定的调光芯片来驱动补光灯的亮…

vue 文本中的\n 、<br>换行显示

一、背景&#xff1a; 后端接口返回数据以\n 作为换行符&#xff0c;前端显示时候需要换行显示&#xff1b; demo&#xff1a; <p style"white-space: pre-wrap;">{{ info }}</p>data() {return {info: 1、优化图片\n 2、 优化时间\n}},项目上&#…

嘎嘎好用的虚拟键盘第二弹之中文输入法

之前还在为不用研究输入中文而暗自窃喜 这不新需求就来了&#xff08;新需求不会迟到 它只是在路上飞一会儿&#xff09; 找到了个博主分享的代码 是好使的 前端-xyq 已经和原作者申请转载了 感谢~~ 原作者地址&#xff1a;https://www.cnblogs.com/linjiangxian/p/16223681.h…

日志打印传值 传引用 右值引用性能测试(Linux/QNX)

结论 Linux平台和qnx平台优化后传值性能都是比传引用的差&#xff0c;也比传右值的差&#xff0c;因此传参时有必要传递引用。 测试代码 #include <cstdint> #include <ctime> #include <string>#ifdef __linux__#define ITERATIONS 10000000 #else#defin…

《Linux运维总结:ARM64架构CPU基于docker-compose一离线部署rabbitmq 3.10.25容器版镜像模式集群工具》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面向不通的客户安装我们的业务系统&…

最新闲鱼小众蓝海虚拟资源,单号日入300+,三天必起店,矩阵放大月入1-2W

详情介绍 本项目售卖的虚拟资源非常小众&#xff0c;宅男的最爱&#xff0c;并且市场一片蓝海&#xff01;只需一步手机&#xff0c;随时随地操作项目&#xff0c;流量巨大&#xff0c;安装教程方法操作三天必起店&#xff0c;消息多到回不过来&#xff0c;一天轻松出个大几十单…

Stable Diffusion Ai绘画模型推荐:二次元Coriander_Mix v1大模型推荐

负tag嵌入式:EasyNegative,badhandv4 此模型经测试是写实偏3D的效果 画质灰暗的话请加&#xff1a;VAE840000 或者负tag&#xff1a;(watermark:2),(blurry:2),fat,paintings,sketches,(worst quality:2),(low quality:2),(normal quality:2),((monochrome)), ((grayscale))…

韩国站群服务器如何提升网站性能与用户体验?

韩国站群服务器如何提升网站性能与用户体验? 在当今数字化时代&#xff0c;网站性能和用户体验对于吸引和保留用户至关重要。为了提供快速、稳定和优质的服务&#xff0c;越来越多的网站管理员开始利用韩国站群服务器来优化其网站性能。本文将探讨如何利用韩国站群服务器来提…

PLM系统推荐:产品全生命周期管理最佳解决方案

PLM系统推荐&#xff1a;产品全生命周期管理最佳解决方案 在当今日益竞争激烈的市场环境中&#xff0c;企业如何高效管理其产品设计、开发和生命周期变得尤为重要。产品生命周期管理&#xff08;PLM&#xff09;系统正是为解决这一难题而诞生的。本文将为您详细介绍几款值得推荐…

AI换脸原理(6)——人脸分割介绍

一、介绍 人脸分割是计算机视觉和图像处理领域的一项重要任务,它主要涉及到将图像中的人脸区域从背景或其他非人脸区域中分离出来。这一技术具有广泛的应用场景,如人脸识别、图像编辑、虚拟背景替换等。 在计算机视觉(CV)领域,经典的分割技术可以主要划分为三类:语义分…

Baidu Comate:智能编码助手,助力编程效率飞跃

文章目录 Baidu Comate智能助手简介安装Baidu ComateBaidu Comate主要功能代码智能补全编程知识问答官方插件函数注释行间注释生成单测代码解释调优建议函数拆分清空对话框help AutoWork工具箱 总结 Baidu Comate智能助手简介 Baidu Comate&#xff0c;Coding Mate Powered by …

临时有事无法及时签字盖章?试试用契约锁设置“代理人”

遇到“领导休假中、在开重要会议、外出考察或者主任医生手术中等”一段时间内不方便或者无法及时签字盖章的情况怎么办&#xff1f;业务推进不了只能干等&#xff1f; 契约锁电子签及印控平台支持印章、签名“临时授权”、“代理签署”&#xff0c;实现指定人、指定时间段、指定…

深入探究MySQL常用的存储引擎

前言 MySQL是一个广泛使用的开源关系型数据库管理系统&#xff0c;它支持多种存储引擎。存储引擎决定了MySQL数据库如何存储、检索和管理数据。不同的存储引擎具有不同的特点、性能表现和适用场景。选择适合的存储引擎对于优化数据库性能、确保数据完整性和安全性至关重要。本…

寻找最佳App分发平台:小猪APP分发脱颖而出

在当今移动应用市场日益饱和的环境下&#xff0c;选择一个合适的App分发平台对于开发者来说至关重要。这不仅关系到应用能否快速触达目标用户&#xff0c;还直接影响到品牌的塑造与市场份额的争夺。本文将深入探讨几大关键因素&#xff0c;帮助开发者判断哪个App分发平台最适合…

Educational Codeforces Round 165 (Div. 2) A~E

A.Two Friends (思维) 题意&#xff1a; 小 A A A想开一个派对。他有 n n n个朋友&#xff0c;他希望至少有 2 2 2个朋友参加他的派对。 i i i 这个朋友最好的朋友是 p i p_i pi​ 。所有的 p i p_i pi​ 都是不同的&#xff0c;对于每一个 i ∈ [ 1 , n ] i \in [1, n] …

【已解决】ModuleNotFoundError: No module named ‘IPython‘

&#x1f60e; 作者介绍&#xff1a;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff0c;视频号&#xff1a;AI-行者Sun &#x1f388; 本文专栏&#xff1a;本文收录于《AI实战中的各种bug…