揭示预处理中的秘密!(二)

目录

 ​编辑

1. #运算符

2. ##运算符

3. 命名约定

4. #undef

5. 命令行定义

6. 条件编译

7. 头文件的被包含的方式

8.嵌套文件包含

9. 其他预处理指令

10. 完结散花


 

                                            悟已往之不谏,知来者犹可追                                                        

创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~

1. #运算符

#运算符将宏的⼀个参数转换为字符串字量。它仅允许出现在带参数的宏的替换列表中。
#运算符所执行的操作可以理解为”字符串化“
当我们有⼀个变量 int a = 10; 的时候,我们想打印出: the value of a is 10 .就可以写:

#define PRINT(n) printf("the value "#n" is %d\n",n);
int main()
{int a = 10;PRINT(a);return 0;
}

运行效果如下~
 

2. ##运算符

## 可以把位于它两边的符号合成一个符号,它允许宏定义从分离的文本片段创建标识符。 ## 被称
为记号粘合
这样的连接必须产生⼀个合法的标识符。否则其结果就是未定义的。
这里我们想想,写⼀个函数求2个数的较⼤值的时候,不同的数据类型就得写不同的函数。
比如:

 

nt int_max(int x, int y)
{
return x>y?x:y;
}
float float_max(float x, float y)
{
return x>yx:y;
}

 但是这样写起来太繁琐了,现在我们这样写代码试试~

#define GENERIC_MAX(type)\
type type##_max(type x,type y)\
{\
return (x > y ? x: y);\
}
使用宏定义不同的函数
GENERIC_MAX(int)//替换到宏体内后int##_max ⽣成了新的符号 int_max做函数名
GENERIC_MAX(float)//替换到宏体内后float##_max ⽣成了新的符号 float_max做函数名
int main()
{int m = int_max(2, 3);printf("m=%d\n", m);float n = float_max(3.5f, 4.5f);printf("n=%f\n", n);return 0;
}

 运行效果如下~

 

在实际开发过程中##使用的很少,很难取出非常贴切的例子
 

3. 命名约定

一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分⼆者。
那我们平时的⼀个习惯是:
把宏名全部大写
函数名不要全部大写

 

4. #undef

这条指令用于移除一个宏定义

1. #undef NAME
2. //如果现存的⼀个名字需要被重新定义,那么它的旧名字⾸先要被移除。

5. 命令行定义

许多C的编译器提供了一种能力,允许在命令行中定义符号。用于启动编译过程。
例如:当我们根据同⼀个源文件要编译出⼀个程序的不同版本的时候,这个特性有点用处。(假定某个程序中声明了⼀个某个长度的数组,如果机器内存有限,我们需要⼀个很小的数组,但是另外⼀个机器内存大些,我们需要⼀个数组能够大些。)

 

#include <stdio.h>
int main()
{
int array [ARRAY_SIZE];
int i = 0;
for(i = 0; i< ARRAY_SIZE; i ++)
{
array[i] = i;
}
for(i = 0; i< ARRAY_SIZE; i ++)
{
printf("%d " ,array[i]);
}
printf("\n" );
return 0;
}

编译指令:

1. //linux 环境演⽰
2.gcc -D ARRAY_SIZE=10 programe.c

6. 条件编译

在编译⼀个程序的时候我们如果要将⼀条语句(一组语句)编译或者放弃是很方便的。因为我们有条件编译指令。
比如说:
调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译。

#include <stdio.h>
#define __DEBUG__
int main()
{
int i = 0;
int arr[10] = {0};
for(i=0; i<10; i++)
{
arr[i] = i;
#ifdef __DEBUG__
printf("%d\n", arr[i]);//为了观察数组是否赋值成功。
#endif //__DEBUG__
}
return 0;
}

常见的条件编译指令:

7. 头文件的被包含的方式

本地文件包含

1. #include"filename"

查找策略:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件⼀样在标准位置查找头文件。如果找不到就提示编译错误。

Linux环境的标准头文件的路径:

1 /usr/include

VS环境的标准头文件的路径:

1. C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include
2. //这是VS2022的默认路径

注意按照自己的安装路径去找。

库文件包含 

1. #include<filename>

 查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。
这样是不是可以说,对于库文件也可以使用“” 的形式包含?
答案是肯定的,可以,但是这样做查找的效率就低些,当然这样也不容易区分是库文件还是本地文件了。

8.嵌套文件包含

我们已经知道, #include 指令可以使另外⼀个文件被编译。就像它实际出现于 #include 指令的
地方一样。
这种替换的方式很简单:预处理器先删除这条指令,并用包含文件的内容替换。
一个头文件被包含10次,那就实际被编译10次,如果重复包含,对编译的压力就比较大。

如果直接这样写,test.c文件中将test.h包含5次,那么test.h文件的内容将会被拷贝5份在test.c中。
如果test.h文件比较大,这样预处理后代码量会剧增。如果⼯程比较大,有公共使用的头文件,被大家都能使用,又不做任何的处理,那么后果真的不堪设想。
如何解决头文件被重复引入的问题?答案:条件编译
每个头文件的开头写:

1. #ifndef __TEST_H__
2. #define __TEST_H__
3. //头⽂件的内容
4. #endif //__TEST_H__

或者

1. #pragma once

就可以避免头文件的重复引入~
 

9. 其他预处理指令

除了以上介绍的预处理指令,还有其他的一些~

1. #error
2. #pragma
3. #line

10. 完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

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

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

相关文章

微信小程序引入Vant插件

Vant官网&#xff1a;Vant Weapp - 轻量、可靠的小程序 UI 组件库 先查看官网的版本 新建一个package.json页面&#xff0c;代码写上&#xff1a;&#xff08;我先执行的npm安装没出package页面&#xff0c;所以先自己创建了一个才正常&#xff09; {"dependencies"…

【软件测试】--功能测试4-html介绍

1.1 前端三大核心 html:超文本标记语言&#xff0c;由一套标记标签组成 标签&#xff1a; 单标签&#xff1a;<标签名 /> 双标签:<标签名></标签名> 属性&#xff1a;描述某一特征 示例:<a 属性名"属性值"> 1.2 html骨架标签 <!DOC…

web组态软件

1、强大的画面显示web组态功能 2、良好的开放性。 开放性是指组态软件能与多种通信协议互联&#xff0c;支持多种硬件设备&#xff0c;向上能与管理层通信&#xff0c;实现上位机和下位机的双向通信。 3、丰富的功能模块。 web组态提供丰富的控制功能库&#xff0c;满足用户的测…

【数据分享】2019-2023年我国地级市逐月新房房价数据(Excel/Shp格式)

房价是一个城市发展程度的重要体现&#xff0c;一个城市的房价越高通常代表这个城市越发达&#xff0c;对于人口的吸引力越大&#xff01;因此&#xff0c;房价数据是我们在各项城市研究中都非常常用的数据&#xff01;之前我们分享过2011-2023年我国地级市逐月二手房房价数据&…

【pytorch】tensor.detach()和tensor.data的区别

文章目录 序言相同点不同点测试实例应用 序言 .detach()和.data都可以用来分离tensor数据&#xff0c;下面进行比较pytorch0.4及之后的版本&#xff0c;.data仍保留&#xff0c;但建议使用.detach() 相同点 x.detach()和x.data返回和x相同数据的tensor&#xff0c;这个新的t…

rpmrebuild 重新制作 rpm

重新制作 rpm 有两种方式 方式一&#xff1a; 1、rpm2cpio xxx.rpm |cpio -idv 2、修改相关文件 3、rpmrebuild -s my.spec xxx.rpm 4、rpmbuild -ba xxx.spec 方式二&#xff1a; 1、rpmrebuild -m /bin/bash -np rpm/xxx.rpm 2、此时我们得到一个交互shell&#xff0c; 3、比…

算法打卡day5|哈希表篇01|Leetcode 242.有效的字母异位词 、19.删除链表的倒数第N个节点、202. 快乐数、1. 两数之和

哈希表基础知识 哈希表 哈希表关键码就是数组的索引下标&#xff0c;然后通过下标直接访问数组中的元素&#xff1b;数组就是哈希表的一种 一般哈希表都是用来快速判断一个元素是否出现集合里。例如要查询一个名字是否在班级里&#xff1a; 要枚举的话时间复杂度是O(n)&…

docker发布dubbo服务 外部程序访问不到问题处理

一、问题简述 程序通过docker向zookeeper注册服务时&#xff0c;会将容器地址(内网地址)作为服务的通信地址。当我们的程序都在容器内相互通信时&#xff0c;可以凭借容器地址相互通信。但是外部程序想要直接通过宿主机取访问服务时&#xff0c;从zk上取到providers的地址&…

【数据结构】从链表到LinkedList类

&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;个人主页&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388; &#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;数据结构专栏&#x1f388;&#x1f388;&#x1f388;&…

标准库中的String类 String(C++)【2】

文章目录 String常用的接口&#xff08;黑框标记的是常用接口&#xff09;string类对象的反向遍历操作第一种第二种 容量string的扩容机制 String常用的接口&#xff08;黑框标记的是常用接口&#xff09; string类对象的反向遍历操作 第一种 通过下表进行遍历 void TestSt…

计算机网络期末复习笔记

一、引言 计算机网络是现代信息技术的核心&#xff0c;涉及计算机、通信、电子等多个领域。在信息时代&#xff0c;计算机网络已经深入到人们生活的各个方面&#xff0c;如社交、购物、教育、科研等。因此&#xff0c;理解和掌握计算机网络的基本概念和原理&#xff0c;对于计…

springboot226经方药食两用服务平台

经方药食两用服务平台的设计与实现 摘要 近年来&#xff0c;信息化管理行业的不断兴起&#xff0c;使得人们的日常生活越来越离不开计算机和互联网技术。首先&#xff0c;根据收集到的用户需求分析&#xff0c;对设计系统有一个初步的认识与了解&#xff0c;确定经方药食两用…

Redis、Memcache、MongoDB三者区别?

使用Redis、Memcache和MongoDB这些工具或数据库取决于具体的需求和应用场景。每种技术都有自己的优势和适用范围。 Redis&#xff1a; 高性能的内存存储&#xff1a;Redis是一个基于内存的数据存储系统&#xff0c;因此读取和写入速度非常快。 丰富的数据结构支持&#xff1a…

RK3568平台 RTC时间框架

一.RTC时间框架概述 RTC&#xff08;Real Time Clock&#xff09;是一种用于计时的模块&#xff0c;可以是再soc内部&#xff0c;也可以是外部模块。对于soc内部的RTC&#xff0c;只需要读取寄存器即可&#xff0c;对于外部模块的RTC&#xff0c;一般需要使用到I2C接口进行读取…

nebula容器方式安装:docker 安装nebula到windows

感谢阅读 基础环境安装安装docker下载nebula 安装数据库命令行安装查询network nebula-docker-compose_nebula-net并初始化查询安装初始使用root&#xff08;God用户类似LINUX的root&#xff09; 关闭服务 安装UI 基础环境安装 安装docker 点我下载docker 下载nebula 数据…

(2024,Sora 逆向工程,DiT,LVM 技术综述)Sora:大视觉模型的背景、技术、局限性和机遇回顾

Sora: A Review on Background, Technology, Limitations, and Opportunities of Large Vision Models 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 2. 背景 2.1…

Presto简介、部署、原理和使用介绍

Presto简介、部署、原理和使用介绍 1. Presto简介 1-1. Presto概念 ​ Presto是由Facebook开发的一款开源的分布式SQL查询引擎&#xff0c;最初于2012年发布&#xff0c;并在2013年成为Apache项目的一部分&#xff1b;Presto 作为现在在企业中流行使用的即席查询框架&#x…

Python全栈工程师课件教程

【百战程序员】Python全栈工程师 描述&#xff1a;Python 被广泛应用于数据分析、机器学习以及 Web 开发等领域&#xff0c;尤其是近些年人工智能的发展更加助推了 Python 的火热程度。 学习 Python 是非科班出身进入程序员岗位的选择。课程体系全新升级&#xff0c;满足学员提…

【华为面试基础题】5键键盘的输出

描述 有一个特殊的 5键键盘&#xff0c;上面有 a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键。 a键在屏幕上输出一个字母 a; ctrl-c将当前选择的字母复制到剪贴板; ctrl-x将当前选择的 字母复制到剪贴板&#xff0c;并清空选择的字母; ctrl-v将当前剪贴板里的字母输出到屏幕; ctrl-a …

求字符串所有整数最小和 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 1.输入字符串s输出s中包含所有整数的最小和&#xff0c;说明&#xff1a;1字符串s只包含a~z,A~Z,,-&#xff0c; 2.合法的整数包括正整数&#xff0c;一个或者多…