【C语言终章】预处理详解(下)
当你看到了这里时,首先要恭喜你!因为这里就是C语言的最后一站了,你的编程大能旅途也将从此站开始,为坚持不懈的你鼓个掌吧!
🥕个人主页:开敲🍉
🔥所属专栏:C语言🍓
🌼文章目录🌼
8. 命名约定
9. #undef
10. 命令行定义
11. 条件编译
12. 头文件的包含
12.1头文件被包含的方式
12.1.1 本地文件包含
12.1.2 库文件包含
12.2 嵌套文件包含
13. 其他预处理指令
8. 命名约定
一般来讲宏和函数的使用语法很相似。所以语言本身没法很好的让我们区分二者,那我们可以从命名的角度来区分二者,我们平时的一个习惯是:
1 把宏命名全部大写
2 函数名不要全部大写
9. #undef
如果我们想要重新定义一个已经定义存在的宏,需要用到这条指令先移除已经存在的宏,例如:
移除后的宏在重新定义以前无法使用。
10. 命令行定义
许多C的编译器提供了一种能力,允许在编译启动时再定义符号,以便在启动编译后根据实际需要设置符号。
例如:当我们根据同一个源文件要编译出一个程序的不同版本的时候,我们就需要用到这种能力(比如假设某个程序中声明了一个某长度的数组,如果这台机器的内存有限,那么这个数组的长度我们就不能太长;但是当我们把这个源文件放到一个内存够大的机器中时,我们又需要这个数组长一些。这个时候就需要我们在编译时根据这台机器实际需要来自己拟定数组的大小)
在Linux系统中我们有如下代码与指令:
#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 gcc -D ARRAY_SIZE = 10 programe.c
11. 条件编译
在编译一个程序的时候我们如果要将一条语句(一组语句)编译或放弃就要用到条件编译指令。
比如说:调试性的代码,保留碍事,删除又可惜(后续可能还会用到),因此我们可以对其进行选择性编译:
常见的条件编译指令:
1 1.
2 #if 常量表达式
3 //...
4 #endif
5 //常量表达式由预处理器求值。
6 如:
7 #define __DEBUG__ 1
8 #if __DEBUG__
9 //..
10 #endif
11 2.多个分⽀的条件编译
12 #if 常量表达式
13 //...
14 #elif 常量表达式
15 //...
16 #else
17 //...
18 #endif
19 3.判断是否被定义
20 #if defined(symbol)
21 #ifdef symbol
22 #if !defined(symbol)
23 #ifndef symbol
24 4.嵌套指令
25 #if defined(OS_UNIX)
26 #ifdef OPTION1
27 unix_version_option1();
28 #endif
29 #ifdef OPTION2
30 unix_version_option2();
31 #endif
32 #elif defined(OS_MSDOS)
33 #ifdef OPTION2
34 msdos_version_option2();
35 #endif
36 #endif
12. 头文件的包含
12.1头文件被包含的方式
12.1.1 本地文件包含
1 #include "filename";
查找策略:现在源文件所在目录下查找,如果该头文件未找到,编译器就像在查找库函数一样在标准位置查找头文件。如果找不到就提示编译错误。
Linux环境标准头文件路径:
1 /usr/include
VS环境的标准头文件的路径:
1 C:\Program Files (x86)\Microsoft Visual Studio 12.0\VS\include
2 //这是VS2013的默认位置
注意按照自己的安装路径去找。
12.1.2 库文件包含
1 #include <filename>
查找头文件直接去标准路径下查找,如果找不到,就提示编译错误。
这样是不是可以说,对于库文件的包含也可以使用"filename"的形式?
答案是可以的,但是效率方面会低一些。因为如果是用"filename"的形式包含,编译器首先去源文件所在目录下查找,找不到后才去库中查找,这样显然去目录查找是多余的。
12.2 嵌套文件包含
我们已经知道,#include指令可以使另外一个文件被编译。就像这个文件真的存在于这条指令中一样。实际上它是替换的。
替换的方式也很简单:预处理器首先删除这条指令,并用该指令包含的文件中的内容全部拷贝替换到这条指令的位置。
那么既然会拷贝数据,如果我们将一个头文件重复包含个几十次,就会导致程序的长度大幅增加。
为了保证头文件不会被重复包含,我们又可以用到上面的条件编译:
1 #define __TEST_H__ //包含__TEST_H__
2 #ifndef __TEST_H__ //如果没有包含TEST__H__,则执行下面的包含头文件操作
3 #include <filename>
4 #endif
或者
1 #pragma once
13. 其他预处理指令
1 #error
2 #pragma
3 #line
4 ....... //这里不再做介绍,详细可以自行去了解
......
#pragma pack() //在前面结构体部分有介绍
详细可以参考《C语言深度剖析》深入学习。
创作不易,点个赞呗,蟹蟹啦~