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

目录

 ​编辑

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://xiahunao.cn/news/2814836.html

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

相关文章

几道特别难搞的数据库面试题

一、多选题(不定项选择) 在下面所列出的条目中&#xff0c;哪些是数据库管理系统的基本功能&#xff1f; A ‍‍ 数据库定义‍‍ B ‍‍ 数据库的建立和维护‍‍ C ‍‍ 数据库存取‍‍ D 数据库和其他软件系统的通信在Mongodb支持的数据类型中&#xff0c;ObjectId&#xff1…

【web APIs】3、(学习笔记)有案例!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、概念其他事件页面加载事件元素滚动事件页面尺寸事件 元素尺寸与位置 二、案例举例电梯导航 前言 掌握阻止事件冒泡的方法理解事件委托的实现原理 一、概念…

设计模式七:责任链模式

文章目录 1、责任链模式2、spring中的责任链模式Spring InterceptorServlet FilterNetty 1、责任链模式 责任链模式为请求创建了一个接收者对象的链&#xff0c;在这种模式下&#xff0c;通常每个节点都包含对另一个节点者的引用。每个节点针对请求&#xff0c;处理自己感兴趣…

鸿蒙应用成企业布局新方向 鸿蒙人才成开年之后“香饽饽”

随着春节假期的结束&#xff0c;职场人也开始返工返岗。与此同时2024年春招季也已拉开帷幕。2月23日&#xff0c;据智联招聘发布的《2024年春招市场行情周报》&#xff08;第一期&#xff09;显示&#xff0c;2024年春节后第一周&#xff0c;依托消费需求释放与制造业返工复产&…

pv、pvc

目录 1、什么是pv和pvc 2、pvc的使用逻辑 3、StorageClass 4、pv和pvc相互作用 5、pv的生命周期中&#xff0c;一般有几种状态&#xff1f; 6、一个pv从创建到销毁的流程 7、nfs使用pv和pvc 7.1、配置nfs存储 7.2这里定义5个PV&#xff0c;并且定义挂载的路径以及访问…

成都规模最大的直播基地为数字经济时代注入新的活力

直播行业近年来在全球范围内迅速崛起&#xff0c;成为了数字经济时代的新业态。作为中国西南地区的中心城市&#xff0c;成都紧跟时代步伐&#xff0c;积极布局直播产业&#xff0c;以成都直播基地为载体&#xff0c;引领直播行业健康、多元发展。 天府锋巢直播产业基地作为成都…

Android和Linux的开发差异

最近开始投入Android的怀抱。说来惭愧&#xff0c;08年就听说这东西&#xff0c;当时也有同事投入去看&#xff0c;因为恶心Java&#xff0c;始终对这玩意无感&#xff0c;没想到现在不会这个嵌入式都快要没法搞了。为了不中年失业&#xff0c;所以只能回过头又来学。 首先还是…

预付费远传水表管理系统

预付费远传水表管理系统是一种为水表计量和管理而设计的先进系统&#xff0c;结合了预付费和远传智能化技术&#xff0c;为用户和水务部门提供了更便捷、高效的水表管理解决方案。通过这种系统&#xff0c;用户能够根据自身需求预付水费&#xff0c;同时水务部门也能实现对水表…

Java 小项目开发日记 01(注册接口的开发)

Java 小项目开发日记 01&#xff08;注册接口的开发&#xff09; 1.项目需求 完成注册接口 2.项目目录 3. 配置文件&#xff08;pom.xml&#xff09; <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…

Apache Bench(ab )压力测试

目录 参数说明示例1&#xff1a;压力测试示例2&#xff1a;测试post接口post数据文件该如何编写&#xff1f; apr_pollset_poll: The timeout specified has expired (70007)apr_socket_recv: Connection reset by peer (104)参考 参数说明 官方文档参考这里。 ab -c 100 -n …

基础!!!吴恩达deeplearning.ai:神经网络中使用softmax

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai 文章目录 softmax作为输出层的神经网络Tensorflow的实现softmax的改进实现数值舍入误差(Numerical Roundoff Errors)sigmoid修改修改softmax 在上一篇博客中我们了解了有关softmax的原理相关内容…

【mysql版本修改】

1、使用telnet确认当前mysql版本号 telnet <MySQL服务器IP地址> <MySQL端口号> telnet 192.168.38.20 33062、使用strings查看/usr/sbin/mysqld中包含版本号的字符串 # 查看/usr/sbin/mysqld文件中是否包含对应的版本号 strings /usr/sbin/mysqld | grep 5.7.30 …

11. Informer 机制总结

Informer 机制 在 Kubernetes 系统中&#xff0c;组件之间通过 HTTP 协议进行通信&#xff0c;在不依赖任何中间件的情况下需要保证消息的实时性、可靠性、顺序性等。那么 Kubernetes 是如何做到的呢&#xff1f;答案就是 Informer 机制。Kubernetes 的其他组件都是通过 clien…

python|闲谈2048小游戏和数组的旋转及翻转和转置

目录 2048 生成数组 n阶方阵 方阵旋转 顺时针旋转 逆时针旋转 mxn矩阵 矩阵旋转 测试代码 测试结果 翻转和转置 2048 《2048》是一款比较流行​的数字游戏​&#xff0c;最早于2014年3月20日发行。原版2048由Gabriele Cirulli首先在GitHub上发布&#xff0c;后被移…

华为手动ipv6-to-ipv4隧道

中间r2的两个接口配置两个地址就行了&#xff0c;其它什么都不用配置 两边出接口R1和R3手动隧道建立&#xff1a;先把IPV4打通&#xff0c;并配置默认路由 再起隧道接口上进行配置&#xff0c;再配置带隧道的默认路由 PC上和上联接口网关只有IPV6地址 最终两个PC可以ping通 …

node 之 http模块

1.什么是http模块 在网络节点中&#xff0c;负责消费资源的电脑叫做客户端&#xff1b;负责对外提供网络资源的电脑&#xff0c;叫做服务器 http模块是node.js官方提供的&#xff0c;用来创建web服务器的模块&#xff0c;通过http模块提供的http.createServer()方法&#xff0c…

武器大师——操作符详解(上)

目录 一、操作符的分类 二、二进制和进制转换 2.1.二进制与十进制的互相转化 2.1.1 二进制转十进制 2.1.2 十进制转二进制 ​编辑 2.2.二进制转8进制和16进制 2.2.1 转8进制 2.2.2 转16进制 三、原码、反码、补码 四、移位操作符 4.1.左移操作符&#xff08;<…

【C语言】linux内核netdev_start_xmit函数

一、中文注释 static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq, bool more) {// 获取网络设备操作集合const struct net_device_ops *ops dev->netdev_ops;int rc;// 调用实际发送数据包的函数&…

【UE 材质】水晶材质

效果 步骤 1. 先在Quixel Bridge上下载冰纹理 2. 新建一个材质&#xff0c;这里命名为“M_Ice”并打开&#xff0c;添加如下纹理采样节点 继续添加如下节点 此时效果如下&#xff1a; 可以看到此时的材质颜色比较浅&#xff0c;如果希望颜色深一点可以继续添加如下节点 此时效…

基于springboot+vue的大学城水电管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…