C语言程序运行:
(一)预处理
//①.条件编译 是在编译之前完成
#include <stdio.h> int main(){ int a=1;int b=2;int c=2; #if a+b>c printf("满足条件");//因为在编译之前完成,故a,b,c此时均无赋值 #endif return 0;}
#if 表达式(一般当做条件编译的条件是宏)
.... //若成立执行这部分
#endif②
#if 表达式
... //若成立执行这部分
#else
....否则执行这部分
#endif③
#if 表达式
... //若成立执行这部分
#elif 表达式
..
#elif 表达式(可以嵌套)
.....
#else
....
#endif
#include <stdio.h>
int main(){
#if 1
printf("1……");
#endif
int a=3;
#if a-1>1
printf("%d,a);
#endif
return 0;
}
因为在是在编译期完成,所以a-1>1为假,不执行printf("%d",a); 此时a在编译器是不存在的。
提前结束宏的作用域&检查这个宏是否存在:
#include <stdio.h>
#include <stdlib.h>
#define NUM 100
int main(){
#ifdef NUM
printf("%d",NUM);
#endif
#ifdef TT //如果没有这个宏
#define TT 99//就自己定义
#endif
printf("%d",NUM);
#undef TT //取消宏的作用
//下面就不能使用TT
}
条件编译做兼容性处理:
//VS的多字节处理:写在头文件之前:
#ifdef UNICODE
#undef UNICODE // 从unicode到多字节 #undef :取消宏的作用域
#endif其他编译命令:
//No.1 # 直接转字符串
//No.2 ## 连接符 产生一个新名字
//No.3 #pragma
//comment 加载静态库
//warning: 忽略提醒
//pack:对齐方式//message:在控制台上打印
//once:#pragma once(避免重复编译)
//No.4 预留宏(文件属性):_FILE_:文件路径; _DATE_:文件日期;_TIME_:文件时间;LINE_:行号(整数)
(二)宏替换
主要有两个作用:
单纯替换:如用一个名字替换一个数字;汉字代码
宏函数:类似于函数调用。
宏统一写在最上面,头文件下面。
结合#和##
多条语句的宏:很容易与已有代码产生冲突,故一般采用do while,使之成为局部变量。
对编译器进行操作:如VS中#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define tostring(num) #num
#define catName(id) name##id //将name与id连接
//多条语句:直接放一行;或者在行末写个连接符\
#define print(data) if(data%2==0) \
printf("偶数");\
else printf("奇数");
int main(){
puts(tostring(123));//将整形123转化为字符串,puts输出字符串。
//任何数字类型均可,C++里有to_string函数,与其功能相似
return 0;
}
代码段:
#include <stdio.h>
#define 整数 int//看情况写‘;’
#define Five 5
//宏函数 --例子:求最大值
#define Max(a,b){if(a>b) printf("%d",a);else printf("%d",b);}
int main()
{
整数 anum=Five;
printf("%d",anum);
int a=9;
Max(a,b);
return 0;
}
使用宏的 优缺点:
优点:
1.用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作需要的时间更多,所以宏比函数在程序的规模和速度方面更胜一筹。 短小精悍,使用频繁
2.函数的参数必须声明为特定的类型(int、double),所以函数只能在类型合适的表达式上使用。反之,这个宏可以用于整型、长整型、浮点数等等,宏是类型无关的。
使用宏的缺点:
1.每次调用宏,一份宏定义的代码插入程序中,除非宏比较短,否则可能会大幅度增加代码的长度。
2.宏无法调试。在预编译(预处理)阶段,已经把 # define 给替换了,已经不再是宏了。
3.宏由于类型无关,也就不够严谨。
3.宏可能会带来运算符优先级的问题,更容易导致程序出错。最好每一个参数都加个括号