1、不带参数的宏定义
#include <stdio.h>
/*
1.所有的预处理指令都是以#开头
2.预处理指令分3种
1>宏定义
2>条件编译
3>文件包含
3.预处理指令在代码翻译成0和1(编译)之前执行
4.预处理指令的位置是随便写的
5.预处理指令的作用域:从编写指令的那一行开始,一直到文件结尾
6.宏名一般用大写或者以k开头,变量名一般用小写
例如:#define kCount 4 在前面加k,表示是常量
*/
// #define 宏名 被替代内容
// #define COUNT 4
// #define kCount 4
int main()
{
char* name = "COUNT";
printf("%s\n", name); // 输出结果为COUNT,双引号内的内容不会被替换。
#define COUNT 4
int ages[COUNT] = {1, 2, 3, 4};
for (int i = 0; i<COUNT; i++) {
printf("%d\n", ages[i]);
}
int a = COUNT; //a = 4
// 从这行开始,COUNT这个宏就失效
#undef COUNT;
return 0;
}
2、带参数的宏定义
#include <stdio.h>
/*
1.带参数的宏定义,只是纯粹的文本替换,不做任何运算
2.简单算术运算,比如加减乘除,带参数的宏定义效率比函数效率高
*/
/*
int sum(int a, int b)
{
return a+b;
}
*/
int main()
{
int a = 10;
int b = 20;
#define sum(v1, v2) v1+v2 //不严谨,最好(v1+v2)//不严谨,最好((v1)+(v2))
//sum(v1, v2) v1+v2
//sum(a, b) a+b
int c = sum(a,b);
printf("c is %d\n", c);
int d = sum(2, 3) * sum(6, 4);
printf("%d\n", d); // 结果为24,而不是5*10=50,由于#define sum(v1, v2) v1+v2 //不严谨2+3*6+4=24
#undef sum(v1, v2);
#define sum(v1, v2) ((v1)+(v2))
//(2+3)*(6+4)=50
int e = sum(2, 3) * sum(6, 4);
printf("%d\n", e);//输出结果为50
#undef sum(v1, v2);
// #define pingfang(a) (a*a)//不严谨
#define pingfang(a) ((a)*(a))// 这样才严谨
int f = pingfang(5+5);
printf("%d\n", f);
#undef pingfang(a);
//int c = sum(a, b);
return 0;
}
3、条件编译
#include <stdio.h>
// 只有写了#if,在最后面必须加上#endif
/*
1.表示定义过MAX这个宏,就编译下面的语句
#if defined(MAX)
...code...
#endif
2.表示没定义过MAX这个宏,就编译下面的语句
#if !defined(MAX)
...code...
#endif
3.表示定义过MAX这个宏,就编译下面的语句
#ifdef MAX
...code...
#endif
4.表示没定义过MAX这个宏,就编译下面的语句
#ifndef MAX
...code...
#endif
*/
#define MAX 10
#define A 10
int main()
{
int a = 10;
/*
if (a == 10)
{
printf("a == 10\n");
}
else if(a == 5)
{
printf("a==5\n");
}
else
{
printf("a其他值\n");
}
*/
/*这种写法有问题,因为a是运行之后才有值10,而现在是条件编译预处理
#if (a == 10)
printf("a == 10\n");
#elif(a == 5)
printf("a==5\n");
#else
printf("a其他值\n");
#endif
*/
#if (A == 10)
printf("A == 10\n");
// 效果是这之后的两句,不参与编译,节省目标.o文件存储空间,减少代码量
#elif(a == 5)
printf("A==5\n");
#else
printf("A其他值\n");
#endif
// 注意#endif不可省略,否则return 0;}不能编译,编译时语法通不过会报错。
#if defined(MAX)
printf("haha\n");
#endif
#if !defined(MAX)
printf("haha\n");
#endif
#ifdef MAX
printf("HAHA\n");
#endif
#ifndef MAX
printf("HAHA\n");
#endif
return 0;
}
4、文件包含
******源程序文件1:zhangsan.c
/*
1.<>表示系统自带的文件,""表示自定义的文件
2.不允许循环包含,比如a.h包含b.h,b.h又包含a.h
*/
#include <stdio.h>
/*
重复声明,语法可以通过,但是增加了编译器的负担,所以把头文件定义为如下:
lisi.h:
#ifndef ABC
#define ABC 33
int sum(int a, int b);
#endif
*/
#ifndef ABC
#define ABC 33
int sum(int a, int b);
#endif
/*
上面的效果是
#define ABC 33
int sum(int a, int b);
这两句参加编译,后面的语句,因为#define ABC 33,所以不再编译,从而保证每次加载编译头文件一次。
*/
#ifndef ABC
#define ABC 33
int sum(int a, int b);
#endif
/*这将导致wangwu.h不被编译
#ifndef ABC
#define ABC 33
int minus(int a, int b);
#endif
*/
#ifndef WANGWU_H
#define WANGWU_H 33
//#define WANGWU_H //这样也可以,就是定义了一个空的宏
int minus(int a, int b);
#endif
#include "lisi.h"
#include "lisi.h"
#include "lisi.h"
#include "wangwu.h"
/*
注意:wangwu.h头文件的宏名不能和lisi.h的宏名一样,因为一样的话,wangwu.h这个文件就不能参与编译了,原理是条件编译,所以一般以头文件名的大写来做宏名,因为各个文件名不一样
*/
int main()
{
int c = sum(10,19);
printf("%d\n", c);
return 0;
}
*******************************************
******源程序文件2:lisi.c
int sum(int a, int b)
{
return a + b;
}
*******************************************
******头文件3:lisi.h
#ifndef ABC
#define ABC 33
int sum(int a, int b);
#endif
*******************************************
******头文件4:wangwu.h
#ifndef WANGWU_H
#define WANGWU_H 33
//#define WANGWU_H //这样也可以,就是定义了一个空的宏
int minus(int a, int b);
#endif