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

😁博客主页😁:🚀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预处理。

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

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

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

相关文章

mac M2 pytorch_geometric安装

我目前的环境是mac M2&#xff0c;我在base环境中安装了pytorch_geometric,仅仅做测试用的&#xff0c;不做真正跑代码的测试 首先我的base环境的设置如下&#xff1a; pip install pyg_lib torch_scatter torch_sparse torch_cluster torch_spline_conv -f https://data.pyg.…

Tomcat隐藏版本号和关闭默认管理页面

一. 隐藏Tomcat异常页面中的版本信息&#xff0c;Tomcat服务器版本号泄露 Tomcat/8.5.xx相关版本号等信息&#xff0c;是不安全的。这会被黑客获取到&#xff0c;利用该版本的其他漏洞对服务器进行异常操作&#xff0c;所以需要隐藏掉。 进入tomcat安装目录 apache-tomcat-8.…

Leetcode2246. 相邻字符不同的最长路径

Every day a Leetcode 题目来源&#xff1a;2246. 相邻字符不同的最长路径 解法1&#xff1a;树形 DP 如果没有相邻节点的限制&#xff0c;那么本题求的就是树的直径上的点的个数&#xff0c;见于Leetcode543. 二叉树的直径。 考虑用树形 DP 求直径。 枚举子树 x 的所有子…

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…

淘宝天猫京东苏宁1688等平台关键词监控价格API接口(店铺商品价格监控API接口调用展示)

淘宝天猫京东苏宁1688等平台关键词监控价格API接口&#xff08;店铺商品价格监控API接口调用展示&#xff09;代码对接如下&#xff1a; item_get-获得淘宝商品详情 公共参数 请求地址: https://o0b.cn/anzexi 名称类型必须描述keyString是调用key&#xff08;必须以GET方式…

Java / Android 多线程和 synchroized 锁

s AsyncTask 在Android R中标注了废弃 synchronized 同步 Thread: thread.start() public synchronized void start() {/*** This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionali…

雅创电子-301099 三季报分析(20231109)

雅创电子-301099 基本情况 公司名称&#xff1a;上海雅创电子集团股份有限公司 A股简称&#xff1a;雅创电子 成立日期&#xff1a;2008-01-14 上市日期&#xff1a;2021-11-22 所属行业&#xff1a;批发业 周期性&#xff1a;0 主营业务&#xff1a;分销东芝、首尔半导体、村田…

golang工程中间件——redis常用结构及应用(set,zset)

Redis 命令中心 这些篇文章专门以应用为主&#xff0c;原理性的后续博主复习到的时候再详细阐述 set 集合&#xff0c;为了描述它的特征&#xff0c;我们可称呼为无序集合&#xff1b;集合的特征是唯一&#xff0c;集合中的元素是唯一存在 的&#xff1b; 存储结构 元素都…

前端构建工具vite与webpack详解

文章目录 前言什么是构建工具先说说企业级项目里都需要具备哪些功能&#xff1f;这是代码改动后需要做的事情样例总结 一、构建工具他到底承担了哪些脏活累活&#xff1f;二、vite相较于webpack的优势三、 vite会不会取代webpack四、 你必须要理解的vite脚手架和vitecreate-vit…

Pytorch卷积神经网络各层介绍与实现

本文将讲解&#xff0c;PyTorch卷积神经网络各层实现与介绍&#xff0c;包括&#xff1a;基本骨架–nn.Module的使用、卷积操作、卷积层、池化层、激活函数、全连接层的介绍。 &#x1f61c; 对于相关原理&#xff0c;可以跳转&#x1f449;卷积神经网络CNN各层基本知识 &…

Nginx缓存基础

1 nginx缓存的流程 客户端需要访问服务器的数据时&#xff0c;如果都直接向服务器发送请求&#xff0c;服务器接收过多的请求&#xff0c;压力会比较大&#xff0c;也比较耗时&#xff1b;而如果在nginx缓存一定的数据&#xff0c;使客户端向基于nginx的代理服务器发送请求&…

FRC-EP系列--你的汽车数据一站式管家

FRC-EP系列产品主要面向汽车动力总成测试的客户&#xff0c;主要应用方向为残余总线仿真及网关。本文将详细介绍FRC-EP的产品特性和应用场景。 应用场景&#xff1a; 汽车电子生成研发过程中&#xff0c;需要对汽车各个控制器进行仿真测试&#xff0c;典型的测试对象有&#…

原语:串并转换器

串并转换器OSERDESE2 可被Select IO IP核调用。 OSERDESE2允许DDR功能 参考&#xff1a; FPGA原语学习与整理第二弹&#xff0c;OSERDESE2串并转换器 - 知乎 (zhihu.com) 正点原子。 ISERDESE2原语和OSERDESE2原语是串并转换器&#xff0c;他的的功能都是实现串行数据和并行…

基于安卓android微信小程序的物流仓储系统

项目介绍 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个开发过程首先对物流仓储系统进行需求分析&#xff0c;得出物流仓储系统主要功能。接着对物流仓储系统进行总体设计和详细…

Halcon的相机内参外参的标定

halcon标定相机内参只能使用方向标定板和圆点标定板。并且方向标定板可也可用性极高。 1.打开halcon的标定助手&#xff0c;选择标定板的描述文件&#xff0c;填写标定板的厚度&#xff0c;根据相机选择像元的尺寸和镜头的焦距。如果已有相机内参&#xff0c;只标定外参&#…

Project#2: Extendible Hash Index

文章目录 准备Task #1-Read/Write Page GuardsBasicPageGuard/ReadPageGuard/WritePageGuardUpgradeWrappersTests Task #2-Extendible Hash Table PagesHash Table Header Pages**成员变量&#xff1a;****方法实现&#xff1a;** Hash Table Directory Pages**成员变量&#…

什么是Node.js的NVM(Node Version Manager)?它的作用是什么?

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

【ZYNQ】裸机 PS + PL 双网口实现之 SDK 程序设计

涉及 lwip 库文件及 ZYNQ 配置相关可参考以下文章&#xff1a; 【ZYNQ】裸机 PS PL 双网口实现之 LWIP 库文件修改 【ZYNQ】裸机 PS PL 双网口实现之 ZYNQ 配置 工程配置 启动 SDK &#xff0c;创建模板工程&#xff0c;配置 BSP。 勾选 lwip141 库。 对 lwip 做如下配置…

Elastic Observability 8.11:ES|QL、APM 中的通用分析和增强的 SLOs

作者&#xff1a;Tom Grabowski, Katrin Freihofner, Israel Ogbole Elastic Observability 8.11 引入了 ES|QL for Observability&#xff08;技术预览版&#xff09;、Universal ProfilingTM 和 Elastic APM 集成&#xff0c;以及针对 Elastic Observability 的新 SLO &#…

GD32单片机远程升级下载,手机在线升级下载程序,GD32在线固件下载升级,手机下载程序固件方法

GD32、STM32单片机&#xff0c;是我们最常见的一种MCU。通常我们在使用STM32单片机都会遇到程序在线升级下载的问题。 GD32/STM32单片机的在线下载通常需要以下几种方式完成&#xff1a; 1、使用ST/GD提供的串口下载工具&#xff0c;本地完成固件的升级下载。 2、自行完成系统B…