编译预处理
编译预处理处于C程序编译第一步骤,基本操作就是提前处理C中以 # 开头的语句,将源代码里一些代码替换新的代码
主要分为:
-
- 宏定义,一般格式:#define name value
- 变量式宏定义
- 函数式宏定义
- 文件包含
#include <filename>
#include "filename"
- 文件包含
- 条件编译
- assert宏
宏定义
源码如下:
#include<stdio.h>
#define NAME "zhangsan"
int main() {
printf(NAME);
return 0;
}
用gcc -E命令可以得到预编译后的代码,如下:
...省略
extern FILE *popen (const char *__command, const char *__modes) ;
extern int pclose (FILE *__stream);
extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
# 914 "/usr/include/stdio.h" 3 4
extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 944 "/usr/include/stdio.h" 3 4
# 2 "example.c" 2
# 3 "example.c"
int main() {
printf("zhangsan");
return 0;
}
注意倒数第三行.NAME替换成为了 “zhangsan”
那么是因为我们写的源码:
#define NAME "zhangsan"
这个""
双引号是自己写的还是预编译自己加的呢?更改为
#define NAME zhangsan
重复之前的gcc -E操作,得到
# 3 "example.c"
int main() {
printf(zhangsan);
return 0;
}
所以,以宏定义的预编译只是单纯的替换文本的操作。
注意:在”NAME” 引号包括起来则不会替换。
可以将宏定义的value定义为表达式巧妙的运算。
变量式宏定义
一般形式: #define 标识符 字符串
#include <stdio.h>
#define PI 2.1415926
#define C (2 * PI * radius)
int main() {
int radius;
float circlue;
printf("Please enter the circle ridius: ");
scanf("%d",&radius);
circlue = C;//使用宏定义
printf("Circle circlue: %f\n",circlue);
return 0;
}
gcc -E a.e,tail a.e 查看
# 4 "define_variable.c"
int main() {
int radius;
float circlue;
printf("Please enter the circle ridius: ");
scanf("%d",&radius);
circlue = (2 * 2.1415926 * radius);
printf("Circle circlue: %f\n",circlue);
return 0;
}
可以看到C被替换了。
函数式宏定义
一般形式: #define 标识符(参数列表) 字符串
把之前的C
宏定义改一下:
#include <stdio.h>
#define PI 2.1415926
#define C(r) 2 * PI * r
int main() {
int radius;
float circlue;
printf("Please enter the circle ridius: ");
scanf("%d",&radius);
circlue = C(radius);
printf("Circle circlue: %f\n",circlue);
return 0;
}
注意函数式宏定义宏名字后没有空格
gcc -E 得到预编译后的代码,tail查看后几行。
# 4 "define_variable.c"
int main() {
int radius;
float circlue;
printf("Please enter the circle ridius: ");
scanf("%d",&radius);
circlue = 2 * 2.1415926 * radius;
printf("Circle circlue: %f\n",circlue);
return 0;
}
嵌套宏定义
#include <stdio.h>
#define A 1
#define B 2
#define ADD A+B
#define C(r) 2 * PI * r
int main() {
int i = ADD;
printf(" %d\n",i);
return 0;
}
多行宏定义
以\换行
#include <stdio.h>
#define exchange(a,b){\
a = b-a;\
b = b-a;\
a = b+a;\
}
int main() {
int i;
int j;
printf("Please enter first num:");
scanf("%d",&i);
printf("Please enter second num:");
scanf("%d",&j);
exchange(i,j);
printf("Exchanged,First num: %d, second: %d\n",i,j);
return 0;
}
文件包含
文件包含也是替换操作。
Test.h
#define DATA "Hello!"
void showData();
Test.c
#include "Test.h"
#include <stdio.h>
void showData() {
printf(DATA);
}
Main.c
#include <stdio.h>
#include "Test.h"
int main() {
printf("调用Test.h的showData方法:\n");
showData();
return 0;
}
根据以上几个文件得到预编译文件Main.i
......
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 944 "/usr/include/stdio.h" 3 4
# 2 "Main.c" 2
# 1 "Test.h" 1
# 2 "Test.h"
void showData();
# 3 "Main.c" 2
int main() {
printf("调用Test.h的showData方法:\n");
showData();
return 0;
}
嵌套包含和条件编译
一般在头文件里定义的时候
#ifndef _TEST_H
#define _TEST_H
#define DATA "Hello!"
void showData();
#endif
网友评论