1.文件包含#include
作用:把指定的源文件或头文件的全部内容包含到当前文件中。
形式1:#include<文件名>,直接按系统标准方式检索文件目录。
形式2:#include"文件名",在当前的源文件的目录中寻找,找不到再按照系统标准方式检索其他文件目录。
2.宏定义#define命令
#include<iostream>
using namespace std;
#define name1 北京邮电大学;
#define name2 "北京邮电大学";
int main()
{
// char n1[] = name1;//预处理后为 char n1[] = 北京邮电大学,非法语句
char n2[] = name2;//预处理后为 char n1[] = "北京邮电大学",合法语句
cout << n2 <<endl;
return 0;
}
(1)带参数的宏定义
作用:除了进行字符序列替换外,在进行参数替换。
形式:#define 宏名(参数列表) 字符序列。
宏替换过程:用指定的字符序列替换宏名,然后用实参替换参数列表中的形参。
#include<iostream>
#include <stdio.h>
#define sq(x) ( (x) * (x) )
using namespace std;
int main()
{
int i = 3, j;
j = sq(i++);//j = ((i++) * (i++));
// j = sq(++i);//结果:25 5
printf("%d %d", j, i);
return 0;
}
注意:<1>不能忽视宏定义中的空格,如:#define f (x) ((x)-1) 被理解为不带参数的宏替换;
<2>“实参”与“形参”应一一对应,无类型而言,仅替换;“实参” 如果是表达式,并不进行运算;
<3>与函数的形参和实参有本质上的区别:不分配内存、参数无类型、表达式不求值、宏展开在预编译时进行(函数调用在运行时进行);
<4>宏替换不占运行时间,只占编译时间;
<5>在定义宏时最好把每个参数都括起来,整个结果表达式也括起来,括号多用于在复杂表达式中遇到的优先级问题:define abs(x) (((x) >= 0) ? (x) : -(x)),如果定义成define abs(x) x > 0 ? x : -x ,abs(a-b)得到a - b > 0 ? a - b : - a - b错误结果 。
(2)宏并不是类型定义
宏的一个常见用途是:使多个不同变量的类型可在一个地方说明,只需要改变一行代码,就能改变f1和a的类型。
<pre name="code" class="cpp">#define FTYPE struct f
FTYPE f1;
FTYPE a;
但是最好使用类型定义:typedef struct f FTYPE。比如:
#define T1 struct f *
typedef struct f *T2;
以上T1,T2都是指向结构体 f 的指针类型,用它们声明多个变量时 ,将出错:
T1 a,b; //展开 struct f *a,b,出错,a定义为指向结构体的指针,b被定义为一个结构体
T2 a,b; //正确
(3)在替换中使用参数
C语言还专门提供了一个特殊的符号作为参数标识,被称为符号参数。符号参数用“#”和“##”表示。“#”是在引用处用参数字符串直接替换,”##”是在引用处的符号参数续接。
#include <iostream>
#include <stdio.h>
using namespace std;
#define pr(x) printf(#x"\n")
#define PI 3.14
#define PI2 6.28
#define PIOut(x) printf("%f\n",PI##x)
int main()
{
pr(abc);
PIOut(2);
return 0;
}
3.条件编译命令
作用:对满足条件的部分程序内容进行编译,否则不参与编译。
功能:便于调试 。
(1)判断符号常量,进行条件编译:
形式1:#ifdef 标识符
程序段
# endif
作用:如果标识符被定义过(一般用#define命令定义),则编译程序段,否则不编译。
形式2:#ifdef 标识符
程序段1
#else
程序段2
# endif
作用:如果标识符被定义过,则编译程序段1,否则编译程序段2。
功能:便于调试 。
(1)判断符号常量,进行条件编译:
形式1:#ifdef 标识符
程序段
# endif
作用:如果标识符被定义过(一般用#define命令定义),则编译程序段,否则不编译。
形式2:#ifdef 标识符
程序段1
#else
程序段2
# endif
作用:如果标识符被定义过,则编译程序段1,否则编译程序段2。
形式3:#ifndef 标识符
程序段
# endif
作用:如果标识符没有被定义过,则编译程序段,否则不编译。
形式4:#ifndef 标识符
程序段1
#else
程序段2
# endif
作用:如果标识符没有被定义过,则编译程序段1,否则编译程序段2 。
程序段
# endif
作用:如果标识符没有被定义过,则编译程序段,否则不编译。
形式4:#ifndef 标识符
程序段1
#else
程序段2
# endif
作用:如果标识符没有被定义过,则编译程序段1,否则编译程序段2 。
(2)判断表达式,进行条件编译:
形式1:#if(表达式)
程序段
# endif
作用:如果表达式成立(表达式为“真”)则编译程序段,否则不编译。
形式2:#if(表达式)
程序段1
#else
程序段2
# endif
作用:如果表达式成立则编译程序段1,否则编译程序段2 。
说明:
①只对在判断范围内的程序段进行条件编译,其它的程序部分均不编译;
②不编译=不可能执行;
③省编译时间,减少目标程序的长度,便于程序移植。
形式1:#if(表达式)
程序段
# endif
作用:如果表达式成立(表达式为“真”)则编译程序段,否则不编译。
形式2:#if(表达式)
程序段1
#else
程序段2
# endif
作用:如果表达式成立则编译程序段1,否则编译程序段2 。
说明:
①只对在判断范围内的程序段进行条件编译,其它的程序部分均不编译;
②不编译=不可能执行;
③省编译时间,减少目标程序的长度,便于程序移植。
#include <iostream>
#include <stdio.h>
using namespace std;
#define Student 1
int main()
{
#ifdef Student
printf("处理学生信息\n");
#if(Student)
printf("处理大学生信息\n");
#else
printf("处理小学生信息\n");
#endif
#else
printf("处理教师信息\n");
#endif // Student
}