c语言学习 预编译处理 宏定义 文件包含 条件编译

一 不带参数的宏定义

一个项目可以通过编译、链接最终形成一个可执行文件。
每个源文件(.cpp),都会单独编译,编译成一个目标文件。
系统把这些文件进行链接,最终形成可执行文件。
预备知识:
编译:笼统地说,语法 ,语法分析,目标文件(临时文件)的生成,优化之类。
一般来讲1.预处理;2.编译:词法 语法分析目标代码生成优化,产生临时文件。
3.汇编,产生.o/.obj文件。
预处理:在源程序.cpp中加入一些特殊的代码,提供一些特殊功能。编译系统会先对特殊代码做处理。这个处理叫预处理。处理结果在和源程序代码进行2中的编译,然后汇编。
//C语言提供三种预处理功能。
1.宏定义
2.文件包含
3.条件编译 这三种功能也是通过写代码实现的,只是以#开头。

不带参数的宏定义是干嘛的? 用一个指定的标识符来代表一个字符串;一般形式 #define 标识符 字符串//标识符也叫宏名
//不带参数的宏定义:用PI代替3.1415926//程序源码中用的是PI
#define PI 3.1415926//

好处:1.用一个简单的名字代替一个长字符串。在预编译时将宏名替换成字符串的过程叫宏展开。#define 宏定义命令
2. 为修改提供了极大的便利。
说明:1. 宏名一般都用大写字母。
2.宏定义 不是c语句,不必在行末加分号。如果加了,则连分号一起替换。
3.宏名的有效范围 从define后到本文件结束,不能跨文件使用。
4.可以用#undef终止宏定义的作用域。
5.用#define进行宏定义时,可以用已经定义的宏。可以层层替换。
#define PPI 2*PI
6.字符串内的字符即使和宏名相同,也不进行替换。

带参数的宏定义

一般形式
#define 宏名(参数表)字符串
用右边的字符串代替宏名(参数表)
#define S(a,b) a*b

int tmp=S(2,3);
//一般字符串中都会包含参数表中指定的参数
如果输入 area = (1+5);//1+51+5,希望(1+5)(1+5)
在形参外增加一个括号 :#define S(a,b) (a)*(b)

宏定义是宏名和带括号的参数之间不能加空格,否则,空格之后的字符都作为替代字符串的一部分了。

宏定义和函数的区别
//1. 函数调用时先求实参表达式值,然后带入形参,而带参数的宏只进行简单的字符替换。
//2.函数调用 是在程序运行时处理,分配临时内存。宏展开是在编译时进行的,展开时不分配内存。
//3.宏的参数没有类型的说法,只是个符号,展开时带入指定字符串中。
//4.使用宏次数多时,宏展开后源程序边长,函数调用不会使源程序边长。
//5.只占用编译时间,不占用运行时间,而函数调用占用的是运行时间(分配内存,传递参数,执行函数体)

#define MAX( x,y) (x)>(y) ?(x):(y)
//宏替换多行语句#define MACROTEST do {\
printf("…") ;\
} while(0);

c语言学习 预编译处理 宏定义 文件包含 条件编译

文件包含

//将另外一个文件的内容包含到本文件中,通过#include命令实现。
一般形式 #include“文件名”
c语言学习 预编译处理 宏定义 文件包含 条件编译#include 常用于#include其他.h文件。即头文件。常常把宏定义,函数说明以及其他一些全局变量外部声明放在头文件中。

说明1.一个include 只能包含一个头文件。
2.文件包含是可以嵌套的。
3.#include包含文件<> “” <>去系统目录找头文件。 “” 去当前目录找头文件。

条件编译

几种形式 1.当标识符被定义过,则对程序段1编译,否则对程序段2编译。#else可以没有
#ifdef 标识符
程序段1(一堆代码)
#else
程序段2
#endif

  1. #ifndef
  2. 当指定的表达式 为非0时编译
    //#if 表达式
    程序段1(一堆代码)
    #else
    程序段2
    #endif

好处1.减少目标文件的长度
2.增加程序的可移植性