ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

《C语言深度剖析》第三章 预处理详解 p2(完结) C语言从入门到入土(进阶篇)

2021-12-17 10:04:03  阅读:158  来源: 互联网

标签:p2 头文件 1.1 编译 ## C语言 进阶篇 条件 预处理


目录

预处理

1. 条件编译

1.1 条件编译如何使用?

1.1.2. #define #ifdef

1.1.3. #ifdef #else

多条件的情况

1.1.4. #ifdefined()

1.1.5.  if defined()多条件判定

1.1.6. 条件编译支持嵌套

1.1.7. #else defined()

1.2.1. 为何要有条件编译?

1.2.2. 条件编译都在哪些地方用?

2. 文件包含

2.1.1 防止头文件重复包含两种:

 2.1.2用 “” 包含的头文件

2.2. #error 预处理

 2.3. #line 预处理

2.4. #pragma

 2.5. # 运算符

2.5.1. printf

2.5.2. #作用: 

2.6. ## 预算符

2.6.1. ##含义

2.6.2. ##作用:

2.6.3. 怎么区分符号和字符串?


本章节文章是作者通过观看《C语言深度剖析》等各种资料总结的精华,基础部分省略了不少,是为了让大家能够更加深入了解C语言的魅力!因为为了避免与之前的文章发生赘述,所以就直接讲作者认为的精华部分哈!现在正文开始!  

 谁都不能阻挡你成为更优秀的人。     

预处理

1. 条件编译

1.1 条件编译如何使用?

首先我们先来了解什么是宏定义,什么是宏真假:

PS:一样是非0为真,0为假。

 

1.1.2. #define #ifdef

 例一:

 例二:

PS:ifndef是相反的,就是没有定义则表达式为真。

1.1.3. #ifdef #else

 例一:

 条件编译:代码裁剪的工具!

 例二:

#if 检测的不止是宏有没有定义,而且要看宏的真假,真才执行#if下面的表达式。

 

当然我们发现这个如果宏定义为空会报错没有定义会走#else下面的表达式。 

  例三:

 VS也可以在预处理时自己输入:

多条件的情况

 

当然也可以不用 ==  也可以用 >  和 < 

1.1.4. #ifdefined()

if defined()  和 ifdef 是一样的功能,判断也是判断宏有没有被定义。

下面是模拟 ifndef,但都是#endif 结束。

1.1.5.  if defined()多条件判定

当然也可以这样:

 

 

1.1.6. 条件编译支持嵌套

 

1.1.7. #else defined()

 

这就可以解决之前说的没有 else if 情况了。

当然如果C CPP 都定义了,就只保留上面的(打印 hello C)。

1.2.1. 为何要有条件编译?

本质认识:条件编译,其实就是编译器根据实际情况,对代码进行裁剪。而这里“实际情况”,取决于运行平台,代码本身的 业务逻辑等。 可以认为有两个好处: 1. 可以只保留当前最需要的代码逻辑,其他去掉。可以减少生成的代码大小 2. 可以写出跨平台的代码,让一个具体的业务,在不同平台编译的时候,可以有同样的表现

1.2.2. 条件编译都在哪些地方用?

举一个例子吧 我们经常听说过,某某版代码是完全版/精简版,某某版代码是商用版/校园版,某某软件是基础版/扩展版等。 其实这些软件在公司内部都是项目,而项目本质是有多个源文件构成的。所以,所谓的不同版本,本质其实就是功能的有无,在技术层面上,公司为了好维护,可以维护多种版本,当然,也可以使用条件编译,你想用哪个版本,就使用哪种条件进行裁剪就行。 著名的Linux内核,功能上,其实也是使用条件编译进行功能裁剪的,来满足不同平台的软件。

2. 文件包含

2.1.1 防止头文件重复包含两种:

一:#pragma once

二:  

但是为什么写头文件先写这个呢?(如何做的,结果我们是知道的)

第一次 _TEST_H_ 没有被定义,接着 #define 定义,然后后面再定义了,

ifndef 为假不执行,就不会重复定义了。

 2.1.2用 “” 包含的头文件

用“ ” 是现在当前目录文件下查找头文件,找不到再去系统文件目录下查找头文件。

而用 <>是直接在系统文件目录下查找头文件。

PS:前面提到了头文件展开,那到底是什么意思呢?

我们发现我们原来的几行代码,但是看预处理有800多行,简单理解就是把

头文件的内容拷贝到目标文件(也有去注释,条件编译等)。

2.2. #error 预处理

预处理都是在编译期间起效果的,也就是和后面的链接,运行没有关系。这点要注意 另外,很多预处理用的并不多,我们这里挑重要的说一下。

 2.3. #line 预处理

 

2.4. #pragma

他们两个的区别就是一个是提示级别的信息,一个是报错级别的信息。

 2.5. # 运算符

相邻字符串具有自动联接特性。 

2.5.1. printf

 注意printf第一个参数就是char*,所以可以直接printf(str),至于后面的 ... 是可变参数列表,后面讲。

将参数符号s对应的文本内容,转换为对应的字符串。

这里就是一开始s为3.1415926然后转换为#3.1415926然后把3.1415926转换为字符串,再打印出来了。

下面是linux里面的,大家可以看右边是预处理之后的结果。

2.5.2. #作用: 

我们现在就可以直接把数字12345直接通过我们定义的 TOSTRING 直接转换为字符串!打印出来的就是12345字符串。

这就比我们之前计算而来的方法要便捷得多!

但是!

这样是不可以的,因为宏是预处理的过程,而开辟空间也是最少到汇编了,所以先一步直接把abc转换为了字符串,打印出来的就是abc。

所以我们要用的话直接写要转的目标就可以了。

2.6. ## 预算符

2.6.1. ##含义

简单说就是把##两边的符号连接起来形成新的符号(如student1就是一个新的符号)。

2.6.2. ##作用:

就比如说我们要打印一个科学记数法的数我们知道底数和他的次方数,就可以用##定义一个新的符号。值得注意的是 ##中写的e ,在编译过程中是有效的!

 

例如:

我们来看看linux预处理后的代码(右边)

2.6.3. 怎么区分符号和字符串?

其实只要记住字符串是用“”引起的,对于字符像我们写的char* str=“abcd”的str,int a的a,还有我们上面的12345转字符串的12345都是符号!还有字符串是程序内部的内容,编译器不会动他,而符号是可被编译器进行改变的(改为编译器所理解的)。

 

今天的内容就到这里了哈!!!

要是认为作者有一点帮助你的话!

就来一个点赞加关注吧!!!当然订阅是更是求之不得!

最后的最后谢谢大家的观看!!!

你们的支持是作者写作的最大动力!!!

下期见哈!!!

 

标签:p2,头文件,1.1,编译,##,C语言,进阶篇,条件,预处理
来源: https://blog.csdn.net/weixin_62700590/article/details/121984633

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有