【维生素C语言】第十七章 - C语言预处理(下)_总程序自定义comm(1)

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

#endif

return 0;

}



> 
>  🚩 运行结果:Hello,World!
> 
> 
> 



💬 代码演示:常量表达式为假



#include <stdio.h>

int main(void) {
#if 0
printf(“Hello,World!\n”);
#endif

return 0;

}



> 
> 🚩 (代码成功运行)
> 
> 
> 



💬 当然也可以用宏替换,可以表示地更清楚:



#include <stdio.h>

#define PRINT 1
#define DONT_PINRT 0

int main(void) {
#if PRINT
printf(“Hello,World!\n”);
#endif

return 0;

}



#### 0x02 多分支的条件编译


![](https://img-blog.csdnimg.cn/2021083109332166.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16)


📚 介绍:多分支的条件编译,直到常量表达式为真时才执行。



💬 代码演示:



#include <stdio.h>

int main(void) {
#if 1 == 2 // 假
printf(“rose\n”);
#elif 2 == 2 // 真
printf(“you jump\n”);
#else
printf(“i jump\n”)
#endif

return 0;

}



> 
> 🚩 代码运行结果:you jump
> 
> 
> 



#### 0x03 条件编译判断是否被定义


![](https://img-blog.csdnimg.cn/20210831104819610.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16)


📚 定义:ifdef 和 if defined() ,ifndef 和 if !defined() 效果是一样的,用来判断是否被定义。



💬 代码演示:



#include <stdio.h>

#define TEST 0
// #define TEST2 // 不定义

int main(void) {
/* 如果TEST定义了,下面参与编译 */
// 1
#ifdef TEST
printf(“1\n”);
#endif

// 2
#if defined(TEST)
printf(“2\n”);
#endif

/* 如果TEST2不定义,下面参与编译 */
// 1
#ifndef TEST2
printf(“3\n”);
#endif

// 2
#if !defined(TEST2)
printf(“4\n”);
#endif

return 0;

}



#### 0x04 条件编译的嵌套


📚 和 **if** 语句一样,是可以嵌套的:



#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif




### 三、文件包含



> 
> 我们已经知道,#include 指令可以使另外一个文件被编译。就像它实际出现于 #include 指令的地方一样。替换方式为,预处理器先删除这条指令,并用包含文件的内容替换。这样一个源文件被包含10次,那就实际被编译10次。
> 
> 
> 


#### 0x00 头文件被包含的方式


![](https://img-blog.csdnimg.cn/20210831112916957.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16)


📚  < > 和 " " 包含头文件的本质区别:查找的策略的区别


① " " 的查找策略:先在源文件所在的目录下查找。如果该头文件未找到,则在库函数的头文件目录下查找。(如果仍然找不到,就提示编译错误)


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



/usr/include


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



C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include



② < > 的查找策略:直接去标准路径下去查找。(如果仍然找不到,就提示编译错误)



❓ 既然如此,那么对于库文件是否也可以使用 " " 包含?


💡 当然可以。但是这样做查找的效率就低些,当然这样也不容易区分是库文件还是本地文件了。为了效率不建议这么做。



💬 代码演示:


①  **add.h**



int Add(int x, int y);


②  **add.c**



int Add(int x, int y) {
return x + y;
}


③  **test.c**



#include <stdio.h>
#include “add.h”

int main(void) {
int a = 10;
int b = 20;
int ret = Add(a, b);
printf(“%d\n”, ret);

return 0;

}



> 
> 🚩 运行结果:30
> 
> 
> 



#### 0x01 嵌套文件的包含


❗  头文件重复引入的情况:


![](https://img-blog.csdnimg.cn/20210831152200654.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> **comm.h** 和 **comm.c** 是公共模块。  
> **test1.h** 和 **test1.c** 使用了公共模块。  
> **test2.h** 和 **test2.c** 使用了公共模块。  
> **test.h** 和 **test.c** 使用了 **test1** 模块和 **test2** 模块。  
>  这样最终程序中就会出现两份 **comm.h** 的内容,这样就造成了文件内容的重复。
> 
> 
> 


❓ 那么如何避免头文件的重复引入呢?


💡 使用条件编译指令,每个头文件的开头写:



#ifndef TEST_H
#define TEST_H
// 头文件的内容
#endif


⚡ 如果嫌麻烦,还有一种非常简单的方法:



#pragma once // 让头文件即使被包含多次,也只包含一份



💭 笔试题:*选自《高质量C/C++编程指南》*


① 头文件中的 ifnde / define / endif 是干什么用的?



> 
> 答:防止头文件被重复多次包含。
> 
> 
> 


② #include <filename.h> 和 #include "filename.h" 有什么区别?



> 
> 答:尖括号是包含库里面的头文件的,双引号是包含自定义头文件的。它们在查找策略上不同,尖括号直接去库目录下查找。而警号双引号是现去自定义的代码路径下查找,如果找不到头文件,则在库函数的头文件目录下查找。
> 
> 
> 









---



![img](https://img-blog.csdnimg.cn/img_convert/4eab558d3b3bbb597e5e6c41dfa8d227.png)
![img](https://img-blog.csdnimg.cn/img_convert/9b7e8cc0e69a842a800b1ea2ebecbe36.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

的代码路径下查找,如果找不到头文件,则在库函数的头文件目录下查找。
> 
> 
> 









---



[外链图片转存中...(img-PC3WsnTE-1715792101106)]
[外链图片转存中...(img-2qs58C7v-1715792101107)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

#DESCRIPTION:Resource namespaces pidns01 pidns01 pidns02 pidns02 pidns03 pidns03 pidns04 pidns04 pidns05 pidns05 pidns06 pidns06 pidns10 pidns10 pidns12 pidns12 pidns13 pidns13 pidns16 pidns16 pidns17 pidns17 pidns20 pidns20 pidns30 pidns30 pidns31 pidns31 pidns32 pidns32 mqns_01 mqns_01 mqns_01_clone mqns_01 -m clone mqns_01_unshare mqns_01 -m unshare mqns_02 mqns_02 mqns_02_clone mqns_02 -m clone mqns_02_unshare mqns_02 -m unshare mqns_03 mqns_03 mqns_03_clone mqns_03 -clone mqns_04 mqns_04 mqns_04_clone mqns_04 -clone netns_netlink netns_netlink netns_breakns_ip_ipv4_netlink netns_breakns.sh netns_breakns_ip_ipv6_netlink netns_breakns.sh -6 netns_breakns_ip_ipv4_ioctl netns_breakns.sh -I netns_breakns_ip_ipv6_ioctl netns_breakns.sh -6I netns_breakns_ns_exec_ipv4_netlink netns_breakns.sh -e netns_breakns_ns_exec_ipv6_netlink netns_breakns.sh -6e netns_breakns_ns_exec_ipv4_ioctl netns_breakns.sh -eI netns_breakns_ns_exec_ipv6_ioctl netns_breakns.sh -6eI netns_comm_ip_ipv4_netlink netns_comm.sh netns_comm_ip_ipv6_netlink netns_comm.sh -6 netns_comm_ip_ipv4_ioctl netns_comm.sh -I netns_comm_ip_ipv6_ioctl netns_comm.sh -6I netns_comm_ns_exec_ipv4_netlink netns_comm.sh -e netns_comm_ns_exec_ipv6_netlink netns_comm.sh -6e netns_comm_ns_exec_ipv4_ioctl netns_comm.sh -eI netns_comm_ns_exec_ipv6_ioctl netns_comm.sh -6eI netns_sysfs netns_sysfs.sh shmnstest_none shmnstest -m none shmnstest_clone shmnstest -m clone shmnstest_unshare shmnstest -m unshare shmem_2nstest_none shmem_2nstest -m none shmem_2nstest_clone shmem_2nstest -m clone shmem_2nstest_unshare shmem_2nstest -m unshare shm_comm shm_comm mesgq_nstest_none mesgq_nstest -m none mesgq_nstest_clone mesgq_nstest -m clone mesgq_nstest_unshare mesgq_nstest -m unshare msg_comm msg_comm sem_nstest_none sem_nstest -m none sem_nstest_clone sem_nstest -m clone sem_nstest_unshare sem_nstest -m unshare semtest_2ns_none semtest_2ns -m none semtest_2ns_clone semtest_2ns -m clone semtest_2ns_unshare semtest_2ns -m unshare sem_comm sem_comm utsname01 utsname01 utsname02 utsname02 utsname03_clone utsname03 -m clone utsname03_unshare utsname03 -m unshare utsname04_clone utsname04 -m clone utsname04_unshare utsname04 -m unshare mountns01 mountns01 mountns02 mountns02 mountns03 mountns03 mountns04 mountns04 userns01 userns01 userns02 userns02 userns03 userns03 userns04 userns04 userns05 userns05 userns06 userns06 userns07 userns07 userns08 userns08 # time namespaces sysinfo03 sysinfo03 clock_nanosleep03 clock_nanosleep03 clock_gettime03 clock_gettime03 timens01 timens01 timerfd04 timerfd04
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值