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

news2024/11/16 18:57:27

目录

引言         

正文         

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

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

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

相关文章

贪心+线段树,CF720A. Closing ceremony

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 720A - Codeforces 二、解题报告 1、思路分析 如果人都在左上角…

顶级SCI优化!24年新算法冠豪猪算法CPO优化无人机集群三维路径规划!先用先发!

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 结果展示 原理讲解 一、路径长度成本 F1 …

斯坦福大学的在线密码学课程

密码学是保护计算机系统信息不可或缺的工具。在本课程中&#xff0c;您将了解密码系统的内部工作原理&#xff0c;以及如何在实际应用中正确使用它们。课程首先将详细讨论当强大的对手窃听和篡改流量时&#xff0c;拥有共享密钥的双方如何进行安全通信。我们将研究许多已部署的…

EtherCAT运动控制器Delta机械手应用

ZMC406硬件介绍 ZMC406是正运动推出的一款多轴高性能EtherCAT总线运动控制器&#xff0c;具有EtherCAT、EtherNET、RS232、CAN和U盘等通讯接口&#xff0c;ZMC系列运动控制器可应用于各种需要脱机或联机运行的场合。 ZMC406支持6轴运动控制&#xff0c;最多可扩展至32轴&#…

【数据库原理及应用】期末复习汇总高校期末真题试卷08

试卷 一、选择题(每题 2 分&#xff0c;共 30 分)    1. ___ ____是长期存储在计算机内的有组织,可共享的数据集合. A.数据库管理系统 B.数据库系统 C.数据库 D.文件组织 2. 数据库类型是按照 来划分…

【ITK配准】第十期 进化优化配准样例

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享ITK配准中的进化优化配准样例,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 进化优化配准 …

Baidu Comate:智能编码,编程效率的革新者

文章目录 一、何为智能编码助手&#xff1f;二、Baidu Comate智能编码助手简介三、Baidu Comate注册四、Baidu Comate体验Comate插件功能1.注释生成代码2.函数注释生成3.行间注释生成4.生成代码解释5. 调优建议 五、插件功能的使用体验感受和建议 &#x1f6a9;结语 一、何为智…

Linux|了解如何使用 awk 内置变量

引言 当我们揭开 Awk 功能部分时&#xff0c;我们将介绍 Awk 中内置变量的概念。您可以在 Awk 中使用两种类型的变量&#xff1a;用户定义的变量和内置变量。 内置变量的值已经在 Awk 中定义&#xff0c;但我们也可以仔细更改这些值&#xff0c;内置变量包括&#xff1a; FILEN…

三.搜索与图论(未完结)

DFS(深搜) 之前写过三篇关于dfs的 练习总结: 基础算法--递归搜索DFS练习总结(上)-CSDN博客 基础算法--递归搜索DFS练习总结(中)-CSDN博客 基础算法--递归搜索DFS练习总结(下)-CSDN博客 以下题目均为 补充练习: P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins …

【隧道篇 / WAN优化】(7.4) ❀ 03. WAN优化的原理 ❀ FortiGate 防火墙

【简介】相信对WAN优化感兴趣的人都会有疑问&#xff0c;WAN优化真的有作用吗&#xff1f;如果真的有作用&#xff0c;那是根据什么原理呢&#xff1f;让我们来更深入的了解一下。 客户端和服务器端 其实很多人在一开始看到WAN优化这个词&#xff0c;就自然的以为上网速度太慢&…

C++学习第十三天(多态)

1、多态的概念 概念 就是指多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生不同的状态 2、多态的定义及实现 多态的构成条件 多态是在不同继承关系的类对象&#xff0c;去调用同一函数&#xff0c;产生了不同的行为。 要在继承中构成…

linux权限维持-HackerPermKeeper

&#x1f512; HackerPermKeeper 通过渗透拿到权限之后&#xff0c;为了不让权限丢失&#xff0c;都会进行权限维持&#xff0c;而在进行权限维持的时候&#xff0c;红队需要花费大量的时候&#xff0c;来验证是否合适&#xff0c;因此在这款工具就诞生 HackerPermKeeper[黑客…

【动态规划】子数组、子串系列I|最大子数组和|环形子数组的最大和|乘积最大子数组|乘积为正数的最长子数组长度

一、最大子数组和 最大子数组和 算法原理&#xff1a; &#x1f4a1;细节&#xff1a; 1.返回值为dp表每个位置的最大值&#xff0c;而不是只看最后一个位置&#xff0c;因为可能最后一个位置都不选 2.可以直接在填dp表的时候就进行返回值的比较 3.如果初始化选择多开一个位…

vue+lodop实现web端打印标签功能

背景&#xff1a;项目要求在web端连接标签打印机&#xff0c;打印收件人信息 lodop打印插件地址&#xff1a;Lodop和C-Lodop官网主站 在项目中使用 1、去官网下载lodop包下载中心 - Lodop和C-Lodop官网主站 windows系统直接下载windows32版的就可以 2、解压安装 点击CLodop…

gtest的编译与使用

文章目录 gtest的编译与使用概述笔记CMake参数官方文档测试程序测试效果END gtest的编译与使用 概述 gTest是 googletest的缩写&#xff0c;如果直接找gTest项目&#xff0c;是找不到的。 库地址 https://github.com/google/googletest.git 迁出到本地后&#xff0c;切到最新…

vue中使用element的i18n语言转换(保姆式教程-保证能用)

1、项目中需要使用的插件&#xff0c;vue2或vue3、element、vue-i18n、js-cookie、vuex我是在vue2中使用 npm i element-ui -S npm i js-cookie -S npm i vue-i18n8.28.2 //因为我项目使用的vue2&#xff0c;直接安装报错了,就下载了固定的版本2、在main.js中引入i18n impor…

买手机参考

买手机一定要看cpu排行榜&#xff0c;避免受外界宣传或干扰等因素等的影响&#xff0c;导致买家消费者被割韭菜。是高等手机还是低等手机&#xff0c;cpu排行榜就是照妖镜。cpu综合处理能力&#xff08;兼顾功耗&#xff09;排行榜如图。 第二张 第三张 第四张

C#语言核心

一、面向对象基本概念 万物皆对象&#xff0c;用程序来抽象&#xff08;形容&#xff09;对象&#xff0c;用面向对象的思想来编程 用中文去形容一类对象&#xff0c;把一类对象的共同点提取出来&#xff0c;然后用程序语言把它翻译过来&#xff0c;带着对象的概念在程序中使…

Excel 查找值的位置后再用位置取值Excel处理

例题描述 Excel 文件中有下图所示的 3 个片区数据 (不同颜色标明)。 现在要算出1-12对应的一列数据&#xff0c;计算规则&#xff1a;在片区3中依次查找1-12&#xff0c;找到后在片区1对应位置取数&#xff0c;如果是0则取片区2同位置的数&#xff0c;如果是1则取F当前查找数。…

docker-compose管理jenkins

1.安装docker和compose 1.docker 更新系统&#xff1a;yum update 安装依赖项&#xff1a;yum install -y yum-utils device-mapper-persistent-data lvm2 配置镜像源&#xff1a;yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce…