黑马程序员——C语言基础---预处理指令
2015-10-27 15:54
453 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
一、简介
C语言在对源程序进行编译之前,会先对一些特殊的预处理指令做解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译。
c语言提供的预处理指令主要有:宏定义、文件包含、条件编译
二、宏定义(宏定义有两种,一种是不带参数,一种是带参数)
1.不带参数的宏定义
格式:#define 宏名 字符串
例如:#define ABC 10
右边的字符串也可以省略,#indefine ABC
它的作用是在编译预处理时,将源程序中所有“宏名”替换成右边的“字符串”,常用来定义常量。
注意点:
1-1.宏名一般都是大写,目的是为了区分变量名,用小写也不会报错,但是这是一种规范。
1-2.对程序中用双引号扩起来的字符串内的字符不进行宏的替换操作。
如
这里“Radio”中的R 不会被替换。
1-3.在编译预处理用字符串替换宏名时,不做语法检查,只会对字符串替换,只有在编译的时候才对展开宏名的源程序进行语法检查。
![](http://img.blog.csdn.net/20151027154000746)
1-4.宏名的有效范围是从定义位置到文件结束。如果需要终止宏定义的作用域,可以用#undef 命令。
1-5.定义一个宏时可以引用已经定义的宏名
使用场景如:
用圆的半径计算周长
运行结果:
![](http://img.blog.csdn.net/20151027155345435)
2.带参数的宏定义
格式:#define 宏名(参数列表) 字符串
注意:
2-1宏名和参数列表之间不能有空格,否则空格后面的所有字符串都作为替换的字符串。
2-2需要用小括号扩住参数列表中的参数
如
结果为
![](http://img.blog.csdn.net/20151027160814190)
这个结果明显不是想要的
所有正确写法是
程序结果
![](http://img.blog.csdn.net/20151027161220439)
三、条件编译
1.概念:如果我们希望程序其中一部分代码只有满足一定条件时才进行编译,否则不参与编译,这就是条件编译。
证明:
代码:
![](http://img.blog.csdn.net/20151027163145486)
编译后文件:
![](http://img.blog.csdn.net/20151027163240373)
这里是880字节
用预处理指令的代码:
![](http://img.blog.csdn.net/20151027163407467)
编译后文件:
![](http://img.blog.csdn.net/20151027163442367)
760字节
四、文件的包含
1.第一种格式 #include <文件名>
这种是直接到C语言库函数头文件所在目录寻找文件
2.第二种格式 #include “文件名”
系统会先在源程序当前目录下寻找,如果找不到,再到操作系统的path路径中查找,最后才到C语言库函数头文件所在目录中寻找。
注意:多次文件包含会降低程序编译效率。
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
一、简介
C语言在对源程序进行编译之前,会先对一些特殊的预处理指令做解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译。
c语言提供的预处理指令主要有:宏定义、文件包含、条件编译
二、宏定义(宏定义有两种,一种是不带参数,一种是带参数)
1.不带参数的宏定义
格式:#define 宏名 字符串
例如:#define ABC 10
右边的字符串也可以省略,#indefine ABC
它的作用是在编译预处理时,将源程序中所有“宏名”替换成右边的“字符串”,常用来定义常量。
注意点:
1-1.宏名一般都是大写,目的是为了区分变量名,用小写也不会报错,但是这是一种规范。
1-2.对程序中用双引号扩起来的字符串内的字符不进行宏的替换操作。
如
#define R 10 int main() { char *s = "Radio"; return 0; }
这里“Radio”中的R 不会被替换。
1-3.在编译预处理用字符串替换宏名时,不做语法检查,只会对字符串替换,只有在编译的时候才对展开宏名的源程序进行语法检查。
#include <stdio.h> #define I 100 int main(int argc, const char * argv[]) { // insert code here... int i[3] = {I}; return 0; }
1-4.宏名的有效范围是从定义位置到文件结束。如果需要终止宏定义的作用域,可以用#undef 命令。
#define PI 3.14 /* 代码段,宏名在这段中还是有效的 */ #undef PI //这里之后就无效了
1-5.定义一个宏时可以引用已经定义的宏名
#define R 3 #define PI 3.14 #define L 2*PI*R #define S PI*R*R
使用场景如:
用圆的半径计算周长
#include <stdio.h> //源程序中所有的宏名PI在编译预处理的时候都会被3.14所替换 #define PI 3.14 //根据圆的半径计算周长 float girth(float radius) { return 2*PI*radius; } int main(int argc, const char * argv[]) { // insert code here... float g = girth(2); printf("周长=%f\n",g); return 0; }
运行结果:
2.带参数的宏定义
格式:#define 宏名(参数列表) 字符串
注意:
2-1宏名和参数列表之间不能有空格,否则空格后面的所有字符串都作为替换的字符串。
2-2需要用小括号扩住参数列表中的参数
如
#include <stdio.h> #define PF(v) (v*v) int main(int argc, const char * argv[]) { // insert code here... int c = PF(5+5)/PF(2+2); printf("c=%d\n",c); return 0; }
结果为
这个结果明显不是想要的
所有正确写法是
#include <stdio.h> #define PF(v) ((v)*(v)) //要替换的参数一定要用小括号扩起来 int main(int argc, const char * argv[]) { // insert code here... int c = PF(5+5)/PF(2+2); printf("c=%d\n",c); return 0; }
程序结果
三、条件编译
1.概念:如果我们希望程序其中一部分代码只有满足一定条件时才进行编译,否则不参与编译,这就是条件编译。
证明:
代码:
编译后文件:
这里是880字节
用预处理指令的代码:
编译后文件:
760字节
四、文件的包含
1.第一种格式 #include <文件名>
这种是直接到C语言库函数头文件所在目录寻找文件
2.第二种格式 #include “文件名”
系统会先在源程序当前目录下寻找,如果找不到,再到操作系统的path路径中查找,最后才到C语言库函数头文件所在目录中寻找。
注意:多次文件包含会降低程序编译效率。
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
相关文章推荐
- c++ 虚函数的实现机制
- C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)
- 颠倒整数(LintCode)
- C、C++中union用法总结
- C++进行base64编码和解码
- C++中的指针和引用
- QT5入门之19 -Qt c++11 支持
- C语言课本实例
- C++对象产生和销毁的顺序
- C++对象产生和销毁的顺序
- effective c++以独立语句将newed对象植入智能指针
- ——黑马程序员——C语言基础--强制类型转换
- leetcode 268 : Missing Number
- 微软承诺将在今年的 Visual C++ 更新中加入 Clang 编译器
- 动态规划解最长公共子序列问题(LCS)C语言加注释
- 微软承诺将在今年的 Visual C++ 更新中加入 Clang 编译器
- Day6.17 C语言简单函数递归调用之求x的y次方
- 一些有趣的C语言面试题
- c语言学习之基础知识点介绍(八):函数的基本用法
- C语言之内存对齐