预编译
1,不带参数的宏定义
宏定义命令#define用来定义一个标识符和一个字符串(常数、表达式、格式字符串等)。一般格式为:#define 宏名 字符串
不需要在行末加分号。
宏替换是以串代替标识符,不分配内存空间。
#define STR "hello, world!"
printf(STR);
注意:
- 1,如果在串中含有宏名,则不进行替换。
printf("This STR is not that STR");//无法替换
- 2,如果串长于一行,可以在行末用一反斜杠‘ \ ’续行。
#define STR "hello,\
world!"
- 3,#define命令出现在函数外面,宏名的有效范围为:定义处到文件结尾。
- 4,可用#undef命令终止宏定义的作用域。
#include <stdio.h>
#define STR "hello"
int main()
{
printf(STR);
#undef STR
}
2,带参数的宏定义
带参数的宏定义不是简单的字符串替换,还要进行参数替换。一般格式为:#define 宏名(参数表) 字符串
#include <stdio.h>
#define HHH(a, b) ((a) * (b) + (b))
//为避免出错,各参数、整体都要有括号
int main()
{
int x = 5, y = 9;
printf("%d", HHH(x, y));//输出5*9+9
return 0;
}
#include <stdio.h>
#define MIN(a, b, c) ((a)>(b) ? ((b)>(c)?(c):(b)) : ((a)>(c)?(c):(a)))
int main()
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
printf("最小值为:%d", MIN(x, y, z));
return 0;
}
注意:
- 1,宏名与参数表之间不可以加空格,否则会将空格以后的所有字符都作为替代字符串的一部分。
- 2,宏定义中,形参不分配内存单元,因此不必声明参数类型。
- 3,用宏替换代替函数可以提高代码的执行速度(因为不存在函数调用)。
- 4,进行宏替换时,不应增加或减少内容,只是简单的替换。
3,#include命令
在一个源文件中使用#include命令可以将另一个源文件的全部内容包含进来。
双引号与尖括号的区别:
尖括号:编译器以标准方式(到存放C库函数头文件所在目录中寻找所要包含的文件)查找头文件;
双引号:编译器会首先在当前目录下查找头文件,如果没有找到,再以标准方式查找。
一般情况下,调用系统自带的库函数,用尖括号(可节省查找的时间);调用用户自己编写的文件,用双引号(用户自己编写的文件通常在当前目录中,如果不在,可在双引号内写明文件路径)。
一个#include命令只能指定1个被包含的文件,这1个文件中又可以嵌套其它文件。若file1中包含file2,那么预编译后两个文件就成为一个文件,file2内若含有全局变量,则在file1中也可以使用。
4,条件编译
1,#if命令
含义:若#if命令后的参数表达式为真,则编译#if与#endif之间的程序段,否则跳过这段程序。#endif命令用来表示#if段的结束。
一般格式为:
#if 常数表达式 //若常数表达式为真,则该段程序被编译,否则跳过不编译。
语句段
#endif
#else的作用是为#if为假时提供另一种选择。
#include <stdio.h>
#define NUM 50
int main()
{
int i = 0;
#if NUM > 50
i ++;
#else
#if NUM < 50
i --;
#else
i += 50;
#endif
#endif//有几个#if 就有几个#endif
printf("%d", i);
return 0;
}
#elif命令用来建立一种“如果…或者如果…”阶梯状多重编译操作选择,这与if语句嵌套中的else if类似
一般格式为:
#if 表达式
语句段
#elif 表达式1
语句段
#elif 表达式2
语句段
...
#elif 表达式n
语句段
#endif
#include <stdio.h>
#define NUM 50
int main()
{
int i = 0;
#if NUM > 50
i ++;
#elif NUM == 50
i += 50;
#else
i --;
#endif
printf("%d", i);
return 0;
}
2,#ifdef命令
#if条件编译指令中,需要判断符号常量所定义的具体值。但在实际应用中,有时我们并不要求判断具体值,只要知道这个符号是否被定义了即可,此时就不需要使用#if,而用另一种条件编译的方法,即#ifdef与#ifndef命令。
#ifdef表示“如果有定义”,一般格式为:
#ifdef 宏替换名
语句段
#endif
//含义为:如果宏替换名已经被定义过,则对语句段进行编译;如果没有定义就不编译。
#ifdef可与#else连用,构成的一般格式为:
#ifdef 宏替换名
语句段1
#else
语句段2
#endif
//含义为:如果宏替换名已经被定义过,则对语句段1进行编译;如果没有定义,就对语句段2进行编译。
#ifndef表示“如果没定义”,一般格式为:
#ifndef 宏替换名
语句段
#endif
//含义为:如果宏替换名没有被定义过,则对语句段进行编译;如果定义过就不编译。
同样,#ifndef也可以与#else连用
#ifndef 宏替换名
语句段1
#else
语句段2
#endif
//含义为:如果宏替换名没有被定义过,则对语句段1进行编译;如果定义过,就对语句段2进行编译。
//例子
#include <stdio.h>
#define STR "hello"
int main()
{
#ifdef STR
printf(STR);
#else
printf("hhh");
#endif
printf("jjj");
#ifdef ABC
printf("ddd");
#else
printf(STR);
#endif
}
3,#indef命令
该命令主要用来删除之前定义的宏定义,使宏名局限在仅需要它们的代码中。一般格式为:
#undef 宏替换名
4,#line命令
#line命令用来改变 _LINE_(存放当前编译行的行号) 与 _FILE_(存放当前编译的文件名) 的内容。
#line 行号["文件名"]
5,#pragma命令
作用是设定编译器的状态,或者指示编译器完成一些特定的动作。
#pragma 参数
参数分为3种情况:
message参数:该参数能够在编译信息输出窗口中输出相应的信息。
code_seg参数:设置程序中函数代码存放的代码段。
once参数:保证头文件被编译一次。
一些预定义替换名
两边都要加下划线_
- _LINE_ :当前被编译代码的行号
- _FILE_ :当前源程序的文件名
- _DATE_ :当前源程序的创建日期
- _TIME_ :当前源程序的创建时间
- _STDC_ :用来判断当前编译器是否为标准C(若值为1,则表示符合标准C;否则不符合)