【C语言 | 预处理】C语言预处理详解(一) —— #define、#under、#if、#else、#elif、#endif、#include、#error

news2024/12/29 9:14:56

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍🍭
😎金句分享😎:🍭🍭

本文未经允许,不得转发!!!

目录

  • 🎄一、概述
  • 🎄二、宏定义(#define、#under)
    • ✨2.1 数值宏常量
    • ✨2.2 字符串宏常量
    • ✨2.3 用 #define 宏定义表达式
    • ✨2.4 #under
  • 🎄三、条件编译(#if、#else、#elif、#endif)
  • 🎄四、文件包含(#include)
  • 🎄五、#error 预处理
  • 🎄六、总结


在这里插入图片描述

🎄一、概述

ANSI标准的C语言预处理指令,见下表:

预处理名称意 义
#define宏定义
#undef撤销已定义过的宏名
#include使编译程序将另一源文件嵌入到带有#include 的源文件中
#if #if 的一般含义是如果#if 后面的常量表达式为 true, 则编译它与#endif 之间的代码,否则跳过这些代码。
命令#endif 标识一个#if 块的结束。
#else命令的功能有点象 C 语言中的 else , #else 建立另一选择(在# if 失败的情况下)。
#elif 命令意义与 else if 相同,它形成一个 if else-if 阶梯状语句,可进行多种编译选择。
#else
#elif
#endif
#ifdef用#ifdef 与#ifndef 命令分别表示“如果有定义”及“如果无定义”,是条件编译的另一种方法。
#ifndef
#line 改变当前行数和文件名称,它们是在编译程序中预先定义的标识符命令的基本形式如下:
#line number["filename"]
#error 编译程序时,只要遇到 #error 就会生成一个编译错误提示消息,并停止编译
#pragma 为实现时定义的命令,它允许向编译程序传送各种指令例如,编译程序可能有一种选择,它支持对程序执行的跟踪。可用#pragma 语句指定一个跟踪选择。

另外 ANSI 标准 C 还定义了如下几个宏:
__LINE__ 表示正在编译的文件的行号
__FILE__ 表示正在编译的文件的名字
__DATE__ 表示编译时刻的日期字符串,例如: “25 Dec 2007”
__TIME__ 表示编译时刻的时间字符串,例如: “12:30:55”
__STDC__ 判断该文件是不是定义成标准 C 程序

在这里插入图片描述

🎄二、宏定义(#define、#under)

#define 宏定义可以出现在代码的任何地方,从本行宏定义开始,以后的代码都认识这个宏了,也可以把任何东西都定义成宏。因为编译器会在预编译的时候,把宏替换成定义的值。

注意: #define 宏不能定义注释符号如:#define BSC //,然后再用BSC去注释。因为注释先于预处理指令被处理,注释处理后,再预处理阶段再出现注释符就会报错

✨2.1 数值宏常量

在C语言中,用#define定义数值常量是很常见的,这样做有几个好处:

  • 用宏定义的数值常量,如果要修改,只需要修改一处即可;而直接用数值的话,则每一处都需要修改;
  • 避免出现“魔鬼数”(直接出现在代码里,不清楚意思的数值),假如直接在代码里return -1;又没有注释的话,谁都不知道-1代表什么意思,这里的-1就是魔鬼数。

数值宏常量可以用作定义数组的维数,也可以放在case关键字后面,而C语言中const修饰的变量都不可以。


✨2.2 字符串宏常量

#define 宏也常常用了定义字符串宏常量,定义字符串宏常量时,最好使用双引号(" ")把字符串引起来。看下面例子:
ENG_PATH_1 定义时没使用双引号,在使用时就需要再加双引号,写成 "ENG_PATH_1" ,否则会报错;
ENG_PATH_2 定义时使用了双引号,可以直接使用ENG_PATH_2去表示字符串。

#define ENG_PATH_1 E:\English\listen_to_this\listen_to_this_3
#define ENG_PATH_2 "E:\English\listen_to_this\listen_to_this_3"

✨2.3 用 #define 宏定义表达式

#define 宏定义表达式时,几个注意点:

  • 注意溢出问题:
     #define SEC_A_YEAR 60*60*24*365		// 这个可能会溢出
     #define SEC_A_YEAR (60*60*24*365)UL
    
  • 定义函数宏时,每个参数示实例都需要用小括号括起来:
    #define SQR (x) x * x	// 如果x=10,没问题;如果x=10+1,则替换后变成 10+1*10+1
    #define SQR (x) ((x) *(x))  // 把参数都多使用括号括起来才保证我们想要的结果
    
  • 函数宏被调用时是以实参代换形参,而不是“值传送”。
  • C语言的宏只能扩展为用大括号括起来的初始化、常量、小括号括起来的表达式、类型限定符(const)、存储类标识符(extern、static)或do-while(0)结构(尽量少用此结构);
  • 函数宏如果有参数的话,则调用时不能缺少、漏写参数;

✨2.4 #under

#under 用了撤销宏定义的,撤销后,后面的代码就不能使用该宏了。也就是说宏的生命周期从#define 开始到#undef 结束。

#define PI 3.141592654// code
#undef PI //后面代码不能使用 PI 了

在这里插入图片描述

🎄三、条件编译(#if、#else、#elif、#endif)

条件编译的功能使得我们可以按不同的条件去编译不同的程序部分, 因而产生不同的目标代码文件。这对于程序的移植和调试是很有用的。条件编译有三种形式,下面分别介绍:

  • 第一种形式:
    // 如果标识符已被 #define 命令定义过则对程序段 1 进行编译,否则对程序段 2进行编译。
    #ifdef 标识符
    程序段 1
    #else
    程序段 2
    #endif
    
  • 第二种形式:
    // 如果标识符未被#define 命令定义过则对程序段 1 进行编译,否则对程序段 2 进行编译。
    #ifndef 标识符
    程序段 1
    #else
    程序段 2
    #endif
    
  • 第三种形式:
    // 如常量表达式的值为真(非 0),则对程序段 1 进行编译,否则对程序段 2 进行编译。
    #if 常量表达式
    程序段 1
    #else
    程序段 2
    #endif
    
    这种形式可以跟 defined() 结合起来,替换前面两种方式
    // 替换第一种方式
    #if defined(标识符)
    程序段 1
    #else
    程序段 2
    #endif
    
    // 替换第二种方式
    #if !defined(标识符)
    程序段 1
    #else
    程序段 2
    #endif
    
    // 其他方式
    #if (defined(__SERVER) && (!defined(__CLIENT)))
    程序段
    #endif
    
    // 与 #elif 一起使用
    #if defined(_SS528V100) || defined(_SS626V100)
    程序段 1
    #elif defined(_SS928V100)
    程序段 2
    #endif
    

在这里插入图片描述

🎄四、文件包含(#include)

文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编译,结果将生成一个目标文件。

文件包含有有两种格式:

  • 格式 1:用尖括号括起来,也称为头文件,表示预处理到系统规定的路径中去获得这个文件;
    #include <filename>
    
  • 格式 2:双引号表示预处理应在当前目录中查找文件名为 filename 的文件,若没有找到,则按系统指定的路径信息,搜索其他目录;
    #include "filename"
    

在这里插入图片描述

🎄五、#error 预处理

#error 预处理指令的作用是,编译程序时,只要遇到 #error 就会生成一个编译错误提示消息,并停止编译。其语法格式为:

#error error-message

注意,宏串 error-message 不用双引号包围。参考下面例子:

#if _SS528V100		
程序段 1
#elif _SS626V100
程序段 2
#else
#error "没有相应宏处理"
#endif

在这里插入图片描述

🎄六、总结

本文介绍C语言的预处理指令:宏定义(#define、#under)、条件编译(#if、#else、#elif、#endif)、文件包含(#include)和#error预处理。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

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

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

相关文章

Python基础教程之十八:Python字典交集–比较两个字典

Python示例&#xff0c;用于查找2个或更多词典之间的常见项目&#xff0c;即字典相交项目。 1.使用“&#xff06;”运算符的字典交集 最简单的方法是查找键&#xff0c;值或项的交集&#xff0c;即 & 在两个字典之间使用运算符。 example.pya { x : 1, y : 2, z : 3 }…

OCR技术狂潮:揭秘最新发展现状,引爆未来智能时代

OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;技术自20世纪以来经历了长足的发展&#xff0c;随着计算机视觉、人工智能和深度学习等领域的进步&#xff0c;OCR技术在准确性、速度和适用范围上都取得了显著的进展。以下是OCR技术发展的现…

Verilog 之 initial 模块与always 模块的用法与差异

文章目录 initial语法和用法特点和注意事项用途 always语法和用法特点和注意事项用途 二者差异 initial 在 Verilog 中&#xff0c;initial 块是用来在模拟开始时执行一次性初始化操作的一种建模方式。它通常用于模拟初始条件或进行一次性的初始化设置&#xff0c;而且只会在模…

深度学习(生成式模型)——Classifier Free Guidance Diffusion

文章目录 前言推导流程训练流程测试流程 前言 在上一节中&#xff0c;我们总结了Classifier Guidance Diffusion&#xff0c;其有两个弊端&#xff0c;一是需要额外训练一个分类头&#xff0c;引入了额外的训练开销。二是要噪声图像通常难以分类&#xff0c;分类头通常难以学习…

聊聊模板引擎<Template engine>

模板引擎是什么 模板引擎是一种用于生成动态内容的工具&#xff0c;通常用于Web开发中。它能够将静态的模板文件和动态数据结合起来&#xff0c;生成最终的HTML、XML或其他文档类型。模板引擎通过向模板文件中插入变量、条件语句、循环结构等控制语句&#xff0c;从而实现根据…

Node.js中的文件系统(file system)模块

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

VS2015模块库交接出现环境报错 error MSB8031 和 error C1189

问题报错 1.错误 MSB8031 Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. 错误 MSB8031不赞成为非Unicode字符集生成MFC项目。您必须将项目属性更改为Unicode&…

【Excel】函数sumif范围中符合指定条件的值求和

SUMIF函数是Excel常用函数。使用 SUMIF 函数可以对报表范围中符合指定条件的值求和。 Excel中sumif函数的用法是根据指定条件对若干单元格、区域或引用求和。 sumif函数语法是&#xff1a;SUMIF(range&#xff0c;criteria&#xff0c;sum_range) sumif函数的参数如下&#xff…

(免费领源码)Node.js#koa#MySQL精品课程网站27724-计算机毕业设计项目选题推荐

目 录 摘要 1 绪论 1.1研究背景 1.2研究现状及意义 1.3koa框架 1.4论文结构与章节安排 2精品课程网站系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.3.2数据修改流程 2.3.3数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析…

QWidget背景图片在Qt Designer 中能显示但运行时不显示的解决方法

目录 1. 现象 2. 解决方法 3. 附录 1. 现象 今天想在QWidget中贴一张png图片作为背景图&#xff0c;在Qt Designer 能显示&#xff0c;但运行时&#xff0c;死活不显示背景图片。样式表设置如下&#xff1a; QWidget {border-image:url(:/untitled2/image/operpanel.png); }…

如何捕捉牛熊转变的信号,澳福认为只需了解一个模式

在过去的交易市场&#xff0c;当所有的多头都买了&#xff0c;没有新的买家时&#xff0c;牛市就结束了。但是在今天的交易市场&#xff0c;激进的卖空者也会出现在趋势的顶部&#xff0c;澳福知道这个事实会改变重要趋势结束时的市场行为。当多头让位于空头时&#xff0c;牛市…

VUE element组件生成的全选框如何获取值

//先声明 const Selection ref([]);//获取 const handleSelectCodeForTicket (val) > {console.log(val);// values.value val;Selection.value [];val.forEach((v) > {Selection.value.push(v);});console.log(Selection.value); }; <el-table selection-change…

vue项目使用pcl.js展示.pcd/.bin点云文件

vue项目使用pcl展示.pcd/.bin点云文件 1.安装pcl.js2.在页面引入pcl及相关js3.开始实例化4.绘制画布注意&#xff1a;报错原因大部分是因为版本改动函数或者方法导致找不到函数或者方法&#xff0c;注意版本&#xff01;&#xff01;&#xff01; 1.安装pcl.js npm install pc…

Linux开发工具之编辑器vim

文章目录 1.vim是啥?1.1问问度娘1.2自己总结 2.vim的初步了解2.1进入和退出2.2vim的模式1.介绍2.使用 3.vim的配置3.1自己配置3.2下载插件3.3安装大佬配置好的文件 4.程序的翻译 1.vim是啥? 1.1问问度娘 1.2自己总结 vi/vim都是多模式编辑器&#xff0c;vim是vi的升级版本&a…

Windows搭建minio存储

minio功能类似以ftp 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.下载软件 https://dl.min.io/server/minio/release/windows-amd64/minio.exe 2.部署配置 我是在D盘下创建了minio目录 minio.exe是软件minio.log是日志&#xff08;不用创建&#xff09;minio900…

Milvus Cloud——Agent 框架工作方式

Agent 框架工作方式 我们以 AutoGPT 为例&#xff0c;看看一个 Agent 框架具体是如何工作的&#xff1a; AutoGPT[2] 使用 GPT-4 来生成任务、确定优先级并执行任务&#xff0c;同时使用插件进行互联网浏览和其他访问。AutoGPT 使用外部记忆来跟踪它正在做什么并提供上下文&am…

数据公网传输加密隧道技术

参考&#xff1a; https://wenku.baidu.com/view/c2bfb9b4d6bbfd0a79563c1ec5da50e2524dd1a1.html?wkts1699578126402

4.Pod详解

4.Pod详解 文章目录 4.Pod详解4.1 Pod介绍4.1.1 Pod结构4.1.2 Pod定义4.1.3 在kubernetes中基本所有资源的一级属性都是一样的&#xff0c;主要包含5部分&#xff1a;4.1.4 在上面的属性中&#xff0c;spec是接下来研究的重点&#xff0c;继续看下它的常见子属性: 4.2 Pod配置4…

scitb包1.5版本发布—增加了统计值的结果和自动判断数据是否正态分布的功能

目前&#xff0c;本人写的scitb包1.5版本已经正式在R语言官方CRAN上线&#xff0c;scitb包是一个为生成专业化统计表格而生的R包。目前只能绘制基线表一。 可以使用以下代码安装 install.packages("scitb")安装过旧版本的从新安装一次就可以升级了 scitb包1.5版本修…

Linux常用命令——cal命令

在线Linux命令查询工具 cal 显示当前日历或指定日期的日历 补充说明 cal命令用于显示当前日历&#xff0c;或者指定日期的日历。 语法 cal(选项)(参数)选项 -l&#xff1a;显示单月输出&#xff1b; -3&#xff1a;显示临近三个月的日历&#xff1b; -s&#xff1a;将星…