1.宏
1)不带参数的宏
/*
* 代码编译为0和1之前执行的语句叫预处理语句。
* 预处理指令以#定义
* 第一种:文件包含,#include
* 第二种:宏定义,#define。#define A B,表示把后文中全部的A换成B
* 宏的生命:无论定义于何处,从定义的一行开始,直到文件结尾,除非遇到#undef。
* 1.不带参宏。
* 2.带参的宏。
* 结束宏,#undef
* 因为是预处理,执行在编译阶段。所以一旦undef,这个宏就注销了,程序在执行阶段很可能访问不到
* 第三种:条件编译,
*/
//一:文件包含
#include <stdio.h>
//二:1.不带参数的宏定义。定义在方法外面,从这里生命开始
//程序自上而下的编译过程汇总,后面代码中全部的count都替换为6,但不包括字符串
#define NUMBER 6 //不能以;结尾。宏名一般用大写
void main() {
int ages[NUMBER] = {3,4,5,6,7,1};
int i;
for(i = 0; i<NUMBER; i++){
printf("%d\t", ages[i]);
}
printf("\n");
#define INT 4376//定义在函数内部,生命从这一行开始
void test(); //声明函数
//尽管紧随宏定义之后的函数里调用了INT,但真正调用发生在程序运行阶段,
//编译阶段,仅仅是把INT替换为4376
test();
//#undef INT //如果在这里注销,就是真的结束宏的生命周期。
//在程序的编译阶段,直到宏结束生命,没有发生替换,毫无意义
printf("%d\n", INT); //如果上一句代码有效,这里将发生错误
//#undef NUMBER
printf("%d\n", NUMBER); //同上
}
void test(){
printf("%d\n", NUMBER);
printf("%d\n", INT);
}
#undef INT //在这里结束宏INT的生命是正确的,因为后续的代码再也用不到INT了
2)带参数的宏
#include <stdio.h>
//定义宏 宏名(参数,参数,...) 替换值(或计算式,不是计算式的结果!)
#define SUM(v1, v2) v1 + v2 //求和宏
//#define SUM(v1, v2) (v1 + v2) //和上面的定义完全是两回事
#define PRODUCT(v1, v2) (v1 * v2) //求积宏
//#define PRODUCT(v1, v2) ((v1) * (v2))
void main() {
int a = 8, b = 7;
//使用宏,传入参数,返回替换值
int sum = SUM(a, b); //!!*发生在编译阶段*!!
//编译后:int sum = a + b = 8 + 7;
printf("%d\n", sum); //15
sum = SUM(2, 3) * SUM(3, 4);
//编译后:sum = 2 + 3 * 3 + 4; ,不是sum=5 * 7; !!!
//定义时加括号,编译后:sum = (2 + 3) * (3 + 4); //运行得35
printf("%d\n", sum); //15
int product = PRODUCT(1+2, 3+4);
//#define PRODUCT(v1, v2) (v1 * v2)
// product = (1+2 * 3+4); //因为宏就是(仅仅是)替换文本!
// product = (1+ 6 +4); //执行阶段发生
// product = 11;
printf("%d\n", product); //11
}
2.条件编译
#define NUMBER 8888 //编译时期的量
#define MAX 5555
void main() {
int i = 7777; //运行时期的量
//满足条件才替换文本
//#if(i == 8888) //编译时期访问运行时期的量无意义
//#if(NUMBER == i) //编译时期访问运行时期的量无意义
#if(NUMBER == 8888) //满足编译条件,代码块会保留给运行阶段使用
if(i == 7777){
printf("7777\n");
}
printf("8888\n");
#elif(NUMBER == 9999) //如果不满足条件,代码块就被删除
printf("9999\n");
#else
printf("0000\n");
#endif //必须有
#ifdef MAX //如果定义了MAX这个宏。
//#if defined(MAX) //等同于上一行
printf("MAX=%d", MAX);
#endif
#ifndef MIN //如果没有定义MIN这个宏
//#if !defined(MIN) //等同于上一行
#define MIN 2222
#endif
}
3.文件包含

1)自定义头文件
/*
首先判断是否包含了该头文件,避免重复include
如果没有定义,就解开;如果已经定义,则忽略
*/
#ifndef _MYH_H_ //------------如果没有定义这个宏,就解开
//首先定义这个没有的宏
#define _MYH_H_
/*
定义头文件,使用一个宏作为钥匙而已
关键是解开自定义的函数
*/
#include <stdio.h> //导入系统头文件。它一定也#ifndef避免重复导入了
void funcMY1(); //声明自定义函数
void funcMY2(int, int);
int funcMY3(int, int);
char *funcMY4();
void funcMY1(){ //实现自定义函数
printf("自定义头文件中的自定义函数\n");
}
void funcMY2(int i, int j){
printf("传入的形参%d, %d\n", i, j);
}
int funcMY3(int i, int j){
return i + j;
}
char *funcMY4(){
return "欢迎使用自定义头文件";
}
#endif //------------解开完毕
2)main主函数文件
/*
* include
* <>系统文件,""自定义文件
* 不允许循环包含。如A文件includeB,同时B文件includeA
* 不建议重复include同一个文件。可:
* #ifndef A
* #define A
* #endif
*/
#include <stdio.h>
#include "myh.h" //引入自定义头文件
void main() {
funcMY1(); //自定义头文件中的自定义函数
funcMY2(222, 333); //传入的形参222, 333
printf("%d\n", funcMY3(555, 666)); //1221
printf("%s\n", funcMY4()); //欢迎使用自定义头文件
}
- end