8 宏定义
约 1184 字大约 4 分钟
2025-06-22
定义宏用 define 去定义宏是在预编译的时候进行替换。 宏定义也可以用小写,但通常用大写字母,作为对变量的区分。
1、不带参宏
#define PI 3.14
在预编译的时候如果代码中出现了 PI 就用 3.14 去替换宏的好处:只要修改宏定义,其他地方在预编译的时候就会重新替换注意:宏定义后边不要加分号。
#define PI 3.1415926
int main()
{
double f;
printf("%lf",PI);
#undef PI//终止PI的作用
retunr 0;
}
宏定义的作用范围,从定义的地方到本文件末尾。如果想在中间终止宏的定义范围可用undef
2、带参宏
#define S(a,b) a*b
int main(int argc,char *argv[])
{
int num;
num=S(2,4)//2*4
num=S(3+5,7)//3+5*7 可以在定义带参宏时加括号
return 0;
}
注意带参宏的形参 a 和b没有类型名,S(2,4) 将来在预处理的时候替换成 实参替代字符串的形参,其他字符保留
3、带参宏和带参函数的区别
带参宏被调用多少次就会展开多少次,执行代码的时候没有函数调用的过程,不需要压栈弹栈。所以带参宏,是浪费了空间,因为被展开多次,节省时间。 带参函数,代码只有一份,存在代码段,调用的时候去代码段取指令,调用的时候要,压栈弹栈。有个调用的过程。 所以说,带参函数是浪费了时间,节省了空间。
带参函数的形参是有类型的,带参宏的形参没有类型名
选择性编译
1、
#ifdef AAA
代码段一
#else
代码段二
#endif
如果在当前.c文件 ifdef 上边定义过 AAA ,就编译代码段一,否则编译代码段二
注意和 if else 语句的区别,if else 语句都会被编译,通过条件选择性执行代码而选择性编译,只有一块代码被编译。
2、
#ifndef AAA
代码段一
#else
代码段二
#endif
和第一种互补。如果在当前.c文件 ifdef 上边没有定义过 AAA ,就编译代码段一,否则编译代码段二。
经常用在防止头文件重复包含。 在fun.h文件中写入内容就可以防止头文件重复包含,两段代码一样
#ifndef __FUN_H__
#define __FUN_H__
extern int fun(int x,int y);
#endif
如果头文件没有重复包含就执行该代码及#endif之前的代码定义宏__FUN_H__,如果重复头文件包含则在第二段的ifndef之前就定义过宏则不执行以后的内容。
3、
#if 表达式
程序段一
#else
程序段二
#endif
如果表达式为真,编译第一段代码,否则编译第二段代码 选择性编译都是在预编译阶段干的事情。
宏函数(带参数的宏)
#define trace(x,y) printf(#x"=%" #y"\n",x)
int main() {
char(* name)[]="tom";
printf("%s\n",name);
trace(name,s);
trace(name,a);
return 0;
}
# 字符串化
# 的意思是把该变量名变为字符串 以trace(name,s)为例
//printf( #x "=%" #y "\n" , x )
//printf("name" "=%" "s" "\n" , name)
//printf("name=%s\n",name)
由于这几个字符串连着所以就将他们合并成一个字符串
续行符\
由于宏定义必须在一行内完成 为了多行定义宏就需要用到续行符表示这一行并未结束后面还有
#define SHOW_SIZEOF_AND_ALIGNOF(T) \
do { \
cout << "sizeof(" << #T << "):\t" << sizeof(T) << ",\t" \
<< "alignof(" << #T << "):\t" << alignof(T) << endl; \
}while(0)
标记拼接
可以将两个变量拼接成字符串
#define trace(x,format) printf(#x"=%"#format "\n",x)
#define trace2(i)trace(salary ## i,d)
int main(void) {
int salary1 = 10000, salary2 = 15000, salary3 = 20000;
trace2(1);
trace2(2);
trace2(3);
return 0;
}
使用宏定义自己的调试语句
#define PRINT(fmt,...) \
printf("[file:%s][func:%s][line:%d]"fmt, \
__FILE__,__FUNCTION__ ,__LINE__,__VA_ARGS__)
int main() {
int sum=0;
for (int i = 0; i < 5; i++) {
sum+=i;
PRINT("sum=%d\n",sum);
PRINT("sum=%d,i=%d\n",sum,i);
}
return 0;
}
宏的可变参数
在宏命名中使用... 表明可变参数 宏定义中使用__VA_ARGS__表示可变参数(编译器的特性)
可以通关宏定义调试宏的开关
#define DEBUG 1
#if DEBUG
#define PRINT(fmt,...) \
printf("[file:%s][func:%s][line:%d]"fmt, \
__FILE__,__FUNCTION__ ,__LINE__,__VA_ARGS__)
#else
#define PRINT(fmt,...)
#endif
在else语句中定义了空的宏函数,通过DEBUG是否为0选择使用哪个宏函数
嵌套定义宏
#define F(f) f (args)
#define args a, b
void test(int n1, int n2) {
printf("%d+%d=%d\n",n1, n2, n1 + n2);
}
int main(void) {
int a = 100,b = 200;
F(test); //100+200=300
//test(args) //test(a,b)}
贡献者
版权所有
版权归属:PinkDopeyBug