四种预编译命令:头文件包含,条件编译,宏替换和布局控制。
文件分别用两种形式包含,一种将文件用“”包含,另一种用<>包含。
两种包含方式的不同之处在于,它们的查找策略不同。
#include<>包含的是库文件,会去系统库所在的文件目录下查找。
#include" "包含的是自己写的头文件,会先在所在的源文件的目录下查找,如果该头文件未找到,编译器就会像查找库函数一样再去系统库所在的文件下查找。
如#define cdz 50,则将在程序中搜索cdz并替换为50。但是注意,搜索的cdz只能是单独的单词,不能嵌入在单词中。如下:
- #include<iostream>
- #define cdz 50
- int main
- {
- std::cout<<fcdzk<<std::endl;
- }
如:#define PFINT printf("hello world!\n");,将会在程序中搜索PFINT的单词,并换成后面的语句实行,将输出hello world!并换行。
如:#define MAX(a, b) ((a)>(b)?(a):(b))
如:#undef add,将会将之前的add的宏定义取消。
#会将后面的变量转为一个字符串
- #define PRT(exp) printf("%s\n",#exp);
- #include
- int main()
- {
- PRT(FRI DAY)
- return 0;
- }
会将前后的两个符号连接在一起。如下:
- #include<stdio.h>
- #define ADD(value1, value2) num1##value2
- int main()
- {
- int a = ADD(114, 514);
- printf("%d \n", a);
- return 0;
- }
其他还有奇奇怪怪的各种宏,但没必要再去全面的了解,遇到之后百度即可。
- __FILE__ // 进行编译的源文件
-
- __LINE__ // 文件当前的行号
-
- __DATE__ // 文件被编译的日期
-
- __TIME__ // 文件被编译的时间
-
- __STDC__ // 如果编译器遵循 ANSI C,其值为1 ,否则未定义 ;
这些符号是c语言内置。如:
- #include<iostream>
- using namespace std;
- int main()
- {
- cout<<__TIME__<<endl;
- return 0;
- }
- #ifndef _MYHEADER_H
- #define _MYHEADER_H
- //头文件内容
-
- #endif
第一次访问该头文件,会定义MYHEADER_H。然后才会执行头文件的内容。
之后在访问该文件,发现MYHEADER_H已经定义。因此头文件的内容将不再执行。
这种在多次包含头文件可能会用到,例如A头文件包含B头文件,C头文件包含B头文件,
如果不加上面的内容,B头文件将被包含两次,将会发生错误。
目的是起到和#ifdef防止重复包含文件一样的作用。但入手点是物理文件下手,#progma once保证
同一物理文件不会被重复包含。
但如果同一头文件有多份拷贝,则不能保证不被重复包含。
但较#ifdef防止重复包含文件,带来的好处是,不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。
例如C++文件都会自动执行#define __cplusplus,因此我们想要仅在C++文件执行下面的内容,而不是C文件,就会像下面那样做:
- #ifdef __cplusplus
-
- //内容
-
- #endif
- #ifndef UNIX
- #error This software requires the UNIX OS.
- #endif
这条指令主要是给出错误信息,上面的这个例子就是,如果没有在UNIX环境下,就会输出This software requires the UNIX OS.然后诱发编译器终止。所以总的来说,这条指令的目的就是在程序崩溃之前能够给出一定的信息。