预处理详解(下)

8. 命名约定

⼀般来讲函数的宏的使⽤语法很相似。所以语⾔本⾝没法帮我们区分⼆者。 那我们平时的⼀个习惯是:

把宏名全部⼤写
函数名不要全部⼤写

  9. #undef

这条指令⽤于移除⼀个宏定义。
# undef NAME
// 如果现存的⼀个名字需要被重新定义,那么它的旧名字⾸先要被移除

 预处理详解(下)_第1张图片

在以上代码的基础上加上#undef ,这里可以理解成一个移除 

预处理详解(下)_第2张图片

 10. 命令⾏定义

许多C 的编译器提供了⼀种能⼒,
允许在命令⾏中定义符号。⽤于启动编译过程。
例如:当我们根据同⼀个源⽂件要编译出⼀个程序的不同版本的时候,这个特性有点⽤处。(假定某
个程序中声明了⼀个某个⻓度的数组,如果机器内存有限,我们需要⼀个很⼩的数组,但是另外⼀个
机器内存⼤些,我们需要⼀个数组能够⼤些。)
#include 
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;
}

 编译指令:

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

 11. 条件编译

在编译⼀个程序的时候我们如果要将⼀条语句(⼀组语句)编译或者放弃是很⽅便的。因为我们有条
件编译指令。
在编译⼀个程序的时候我们如果要将⼀条语句(⼀组语句)编译或者放弃是很⽅便的。因为我们有条
件编译指令。
#include 
#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;
}

预处理详解(下)_第3张图片

如果把232行代码屏蔽掉那么这段代码就会消失(不参与编译)如下:

预处理详解(下)_第4张图片

 常⻅的条件编译指令:

1.
#if 常量表达式
 //...
#endif
//常量表达式由预处理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
 //..
#endif
2.多个分⽀的条件编译
#if 常量表达式
 //...
#elif 常量表达式
 //...
#else
 //...
#endif
3.判断是否被定义
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.嵌套指令
#if defined(OS_UNIX)
 #ifdef OPTION1
 unix_version_option1();

 最简单的条件编译可以这样写:

预处理详解(下)_第5张图片

 预处理详解(下)_第6张图片

#if 后面是真那么编译,如果是假那么就不编译

12. 头⽂件的包含

12.1 头⽂件被包含的⽅式:

12.1.1 本地⽂件包含

#include "filename"

预处理详解(下)_第7张图片

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

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

/usr/include

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

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

 注意按照⾃⼰的安装路径去找。

12.1.2 库⽂件包含 

# include

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

用双引号的形式的查找范围更大,但这样代码的运行效率也自然会下降,就好比全局变量和局部变量,想写出一个优秀的代码就应该早期就要养成良好习惯,库头文件用尖括号,自己写的双引号 

 12.2 嵌套⽂件包含

 test.c

#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
int main()
{
 
 return 0;
}

 test.h

void test();
struct Stu
{
 int id;
 char name[20];
};
如果直接这样写,test.c⽂件中将test.h包含5次,那么test.h⽂件的内容将会被拷⻉5份在test.c中。
如果test.h ⽂件⽐较⼤,这样预处理后代码量会剧增。如果⼯程⽐较⼤,有公共使⽤的头⽂件,被⼤家
都能使⽤,⼜不做任何的处理,那么后果真的不堪设想。
如何解决头⽂件被重复引⼊的问题?答案:条件编译。
每个头⽂件的开头写:
#ifndef __TEST_H__
#define __TEST_H__
//头⽂件的内容
#endif //__TEST_H__

  或者

#pragma once  

就可以避免头⽂件的重复引⼊。
注:
推荐《⾼质量C/C++编程指南》中附录的考试试卷(很重要)。
笔试题:
1. 头⽂件中的 ifndef/define/endif是⼲什么⽤的?
2. #include 和 #include "filename.h"有什么区别?

13. 其他预处理指令

#error
#pragma
#line
...
不做介绍,⾃⼰去了解。
#pragma pack()在结构体部分介绍。
参考《C语⾔深度解剖》学习

你可能感兴趣的:(java,算法,数据结构)