编译预处理指令:对源程序编译之前做一些处理,生成扩展C源程序
在C语言源程序中允许用一个标识符来表示一个字符串,称为“宏”。被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”
宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的
格式:#define 宏名 宏替换值
作用:在进行编译预处理的时候,编译器会对程序中出现的所有的宏名使用宏字符串去进行替换–宏替换仅为简单字符替换
实例:
#include
#define PI 3.1415 //宏名PI,替换所用的字符串3.1415
int main(int argc, char *argv[])
{
int r = 5;
float s;
s = (float)PI * r * r;
printf("s = %7.2f\n", s);
r = 4;
s = (float)PI * r * r;
printf("s = %7.2f\n", s);
return 0;
}
该程序预处理以后main函数会变成如下形式:
int main(int argc, char *argv[])
{
int r = 5;
float s;
s = (float)3.1415 * r * r;
printf("s = %7.2f\n", s);
r = 4;
s = (float)3.1415 * r * r;
printf("s = %7.2f\n", s);
return 0;
}
在C中经常使用宏来定义常量–所以经常把C中的常量叫做符号常量
#include
#define PI 3.1415 //宏名PI,替换所用的字符串3.1415
#define RC PI * 5.0
#define VAL PI + 5 //在定义复杂的宏的时候一定要注意避免出现副作用,因为宏替换只是简单的字符替换
#define VAL1 ((PI) + 5)
int main(int argc, char *argv[])
{
int r = 5;
float s;
s = (float)PI * r * r;
printf("s = %7.2f\n", s);
r = 4;
s = (float)PI * r * r;
printf("s = %7.2f\n", s);
s = RC; //s = 3.1415 * 5.0
printf("s = %7.2f\n", s);
s = VAL * r * r; //PI + 5 * r * r
printf("s = %7.2f\n", s);
s = VAL1 * r * r; //PI + 5 * r * r
printf("s = %7.2f\n", s);
return 0;
}
[root@localhost 10_bits]# gcc test3.c -o test3
[root@localhost 10_bits]# ./test3
s = 78.54
s = 50.26
s = 15.71
s = 83.14
s = 130.26
#include
#define PI 3.1415 //宏名PI,替换所用的字符串3.1415
#define MAX(x, y) x > y ? x : y //x和y成为带参宏的形参
int main(int argc, char *argv[])
{
int num1 = 12;
int num2 = 21;
int res = MAX(num1, num2); //在使用带参宏的时候要将对应的实参传递给形参 -- 和函数调用是一样的
printf("res = %d\n", res);
return 0;
}
上述代码进行宏替换以后称为:
int main(int argc, char *argv[])
{
int num1 = 12;
int num2 = 21;
int res = num1 > num2 ? num1 : num2; //在替换过程中除了将带参宏定义中的宏值替换宏名以外,还会将实参替换宏定义中的形参
printf("res = %d\n", res);
return 0;
}
带参宏和函数调用的区别:
#include
#define PI 3.1415 //宏名PI,替换所用的字符串3.1415
#define MAX(x, y) x > y ? x : y
/*
int MAX(int x, int y)
{
return x > y ? x : y;
}
*/
int main(int argc, char *argv[])
{
int num1 = 12;
int num2 = 21;
double dnum1 = 1.23;
double dnum2 = 2.32;
double dres = MAX(dnum1, dnum2);
int res = MAX(num1, num2);
//res = MAX(dnum1, dnum2);
printf("res = %d\n", res);
printf("dres = %7.2f\n", dres);
return 0;
}
[root@localhost 10_bits]# gcc test3.c -o test3
[root@localhost 10_bits]# ./test3
res = 2
dres = 2.32
在编译预处理过程中,会将包含的文件的内容替换到本文件 中
在头文件中定义数据结构,函数原型
在一个c源程序中实现函数
在主程序中调用函数
比如在stu.h中定义学生结构体和函数原型
typedef struct Stu
{
int no;
char name[12];
float score;
}Stu;
void show_stu(Stu tmp);
在stu.c中实现stu.h中定义的函数
#include "stu.h"
#include
void show_stu(Stu tmp)
{
printf("%d, %s, %7.2f\n", tmp.no, tmp.name, tmp.score);
}
在main.c中调用函数
#include
#include "stu.h"
int main(int argc, char *argv[])
{
Stu st = {101, "Jack", 88.5};
show_stu(st);
return 0;
}
[root@localhost student_manager]# gcc stu.c main.c -o main
[root@localhost student_manager]# ./main
101, Jack, 88.50
#include
int main(int argc, char *argv[])
{
int num1 = 10;
int num2 = 20;
int res;
#ifdef SUM
res = num1 + num2;
#else
res = num2 - num1;
#endif
printf("res = %d\n", res);
return 0;
}
该代码编译预处理以后会变成如下:
int main(int argc, char *argv[])
{
int num1 = 10;
int num2 = 20;
int res;
res = num2 - num1;
printf("res = %d\n", res);
return 0;
}
如果程序原型为:
#include
#define SUM
int main(int argc, char *argv[])
{
int num1 = 10;
int num2 = 20;
int res;
#ifdef SUM
res = num1 + num2;
#else
res = num2 - num1;
#endif
printf("res = %d\n", res);
return 0;
}
则编译预处理以后为:
int main(int argc, char *argv[])
{
int num1 = 10;
int num2 = 20;
int res;
res = num1 + num2;
printf("res = %d\n", res);
return 0;
}
所以条件编译是根据条件十分满足来确定需要编译的语句块
#ifdef … #else … #endif结构是根据指定的标识符是否定义来确定要编译的语句,如果指定标识符在条件编译语句之前已经定义了,选择ifdef部分的语句进行编译(ifdef或者else部分可以是多条件语句,并且不需要使用大括号),如果指定的标识符没有定义则选择else部分的语句进行编译
条件编译还有另外一种结构#ifndef … #else … #endif
所以前面多文件工程应该写成
stu.h
#ifndef __MYHEAD
#define __MYHEAD
typedef struct Stu
{
int no;
char name[12];
float score;
}Stu;
#endif
head1.h
#ifndef __HEAD_1
#define __HEAD_1
#include "stu.h"
void show_stu(Stu tmp);
#endif
stu.c
#include "stu.h"
#include "head1.h"
#include
void show_stu(Stu tmp)
{
printf("%d, %s, %7.2f\n", tmp.no, tmp.name, tmp.score);
}
main.c
include <stdio.h>
#include "stu.h"
#include "head1.h"
int main(int argc, char *argv[])
{
Stu st = {101, "Jack", 88.5};
show_stu(st);
return 0;
}
我们也经常使用条件编译语句来进行调试
#include
#define SUM
//#define DEBUGER
int main(int argc, char *argv[])
{
int num1 = 10;
int num2 = 20;
int res;
#ifdef DEBUGER
printf("ok1\n");
#endif
#ifndef SUM
res = num1 + num2;
#else
res = num2 - num1;
#endif
printf("res = %d\n", res);
#ifdef DEBUGER
printf("ok2\n");
#endif
return 0;
}