【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>
    
    Linux下,系统路径可能有下面这些:
    /usr/include/
    /usr/local/include/
    /usr/lib/gcc/x86_64-linux-gnu/4.8.4/include/
    
  • 格式 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.mzph.cn/news/140989.shtml

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

相关文章

“第六十七天”

各位&#xff0c;昨天查找子串的方法想起来了&#xff0c;就是那个KMP算法......自己理解都有点困难&#xff0c;还看看能不能想一下&#xff0c;确实很困难啊。 不要忘了toupper函数和tolower函数不是直接改变字符的大小写&#xff0c;而是返回对应的大小写的值&#xff0c;需…

文件上传 [ACTF2020 新生赛]Upload1

打开题目&#xff0c;发现是一道文件上传题目 随便上传个一句话木马上去 发现网站前端有白名单限制&#xff0c;只能上传含有jpg&#xff0c;png&#xff0c;gif的后缀文件 那我们便传个2.jpg的一句话木马上去&#xff0c;bp抓包 我们改成php文件后缀试试&#xff0c;发现重发…

毕业设计项目:基于java+springboot的共享单车信息网站

运行环境 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Ma…

5. HTML常用标签

5.1 标签语义 学习标签是有技巧的&#xff0c;重点是记住每个标签的语义。简单理解就是指标签的含义。即这个标签是用来干嘛的。 根据标签的语义&#xff0c;在合适的地方给一个最为合理的标签。可以让页面结构给清晰。 5.2 标题标签 <h1>-<h6>(重要) HTML提供了…

【学习辅助】Axure手机时间管理APP原型,告别手机控番茄任务模板

作品概况 页面数量&#xff1a;共 30 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;时间管理、系统工具 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本品为「手机时间管理」APP原型&#xff0c;…

Redis集群,你真的学会了吗?

目录 1、为什么引入集群 1.1、先来了解集群是什么 1.2、哨兵模式的缺陷 引入集群解决了什么问题 1.3、使用集群&#xff0c;如何存储数据 2、三种主流的分片方式【经典面试题】 2.1、哈希求余算法 2.1.1、哈希求余算法的介绍 2.1.2、哈希求余算法如何扩容 2.2、一致性…

C# 并发编程

C# 并发编程 前言 对于现在很多编程语言来说&#xff0c;多线程已经得到了很好的支持&#xff0c; 以至于我们写多线程程序简单&#xff0c;但是一旦遇到并发产生的问题就会各种尝试。 因为不是明白为什么会产生并发问题&#xff0c;并发问题的根本原因是什么。 接下来就让…

vcomp120.dll丢失怎么办?vcomp120.dll丢失的解决方法分享

vcomp120.dll丢失”。这个错误通常会导致某些应用程序无法正常运行&#xff0c;给用户带来困扰。那么&#xff0c;当我们遇到这个问题时&#xff0c;应该如何修复呢&#xff1f;下面我将为大家介绍四个修复vcomp120.dll丢失的方法。 一、使用dll修复程序修复 可以通过百度或许…

矢量绘图软件Sketch 99 for mac

Sketch是一款为用户提供设计和创建数字界面的矢量编辑工具。它主要用于UI/UX设计师、产品经理和开发人员&#xff0c;帮助他们快速设计和原型各种应用程序和网站。 Sketch具有简洁直观的界面&#xff0c;以及丰富的功能集&#xff0c;使得用户可以轻松地创建、编辑和共享精美的…

NSF服务器

目录 1.简介 1.1 NFS背景介绍 1.2 生产应用场景 2.NFS工作原理 2.1 实例图 2.2 流程 3.NFS的使用 3.1.安装 3.2.配置文件 3.3.主配置文件分析 3.4 实验 服务端&#xff1a; 客户端&#xff1a; 3.5.NFS账户映射 3.5.1.实验2 3.5.2.实验3 4.autofs自动挂载服务…

Mysql学习笔记--基础

一&#xff0c;SQL最重要的增删改命令格式 1&#xff0c;insert into 表名&#xff08;不写这个括号里面的内容就默认所有字段都要添加&#xff09; values&#xff08;&#xff09; 插入单条数据 2&#xff0c;insert into 表名 (里面是列名) values&#xff08;根据列名依次…

Java Web——前端HTML入门

目录 HTML&CSS3&JavaScript简述 1. HTML概念 2. 超文本 3. 标记语言 4. HTML基础结构 5. HTML基础词汇 6. HTML语法规则 7. VS Code 推荐使用的插件 8. 在线帮助文档 HTML&CSS3&JavaScript简述 HTML 主要用于网页主体结构的搭建&#xff0c;像一个毛坯…

【LeetCode:715. Range 模块 | 线段树】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Django(四、路由层)

文章目录 一、路由层1.路由匹配url方法第一个是参数 的正则表达式 二、正则无名分组与有名分组无名分组有名分组 三、反向解析1.概念无名分组动态路由解析有名分组动态路由解析 四、路由分发为什么要用路由分发&#xff1f; 1.总路由分发配置名称空间 五、伪静态的概念六、虚拟…

超级干货:光纤知识总结最全的文章

你们好&#xff0c;我的网工朋友。 光纤已经是远距离有线信号传输的主要手段&#xff0c;而安装、维护光纤也是很多人网络布线的基本功。 在网络布线中&#xff0c;通常室外楼宇间幢与幢之间使用的是光缆&#xff0c;室内楼宇内部大都使用的是以太网双绞线&#xff0c;也有使用…

企业微信开发教程一:添加企微应用流程图解以及常见问题图文说明

最近在前辈的基础上新添加了一个企微应用&#xff0c;过程中遇到了一些卡点&#xff0c;这里一一通过图片标注与注释的方式记录一下&#xff0c;希望能给后来人提供一些清晰明了的帮助&#xff0c;话不多说&#xff0c;大家直接看图吧。 &#xff08;文中包括一些本项目独有的配…

linux下使用Docker Compose部署Spug实现公网远程访问

&#x1f4d1;前言 本文主要是linux下使用Docker Compose部署Spug实现公网远程访问的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &am…

游戏平台采集数据

首先&#xff0c;你需要在你的项目中添加Kotlin的网络库&#xff0c;例如OkHttp。你可以在你的build.gradle文件中添加以下依赖&#xff1a; dependencies {implementation com.squareup.okhttp3:okhttp:4.9.0 }然后&#xff0c;你可以使用以下代码来创建一个基本的网络爬虫&a…

5年测试经验之谈:2年功能测试、3年自动化测试,从入门到25k...

毕业3年了&#xff0c;学的是环境工程专业&#xff0c;毕业后零基础转行做软件测试。 已近从事测试行业8年了&#xff0c;自己也从事过2年的手工测试&#xff0c;从事期间越来越觉得如果一直在手工测试的道路上前进&#xff0c;并不会有很大的发展&#xff0c;所以通过自己的努…