预定义符号
已经约定好了的符号
__STDC__ 如果编译器遵循 ANSIC,他的值就是 1 否则就是未定义的。
int main() { printf("%s\n",__FILE__);//当前文件路径 printf("%s\n",__DATE__);//被编译的日期 printf("%s\n",__TIME__);//被编译的时间 printf("%d\n",__LINE__);//当前代码的行号 printf("%s\n",__STDC__);//当前环境是为定义的 return 0; }
#define 定义符号
#define 可以定义很多东西,比如 ,常量 10000、'a'
还能定义关键字 ,一段代码,一个函数,字符串,等等等。
#define 定义函数
//定义一个符号,内容是一个函数 #define FUNCTION int add(int x , int y)\ {\ return x + y ;\ } //使用这个函数 FUNCTION int main() { int a = 66; int b = 43; //对函数进行传参 int ret = add(a, b); printf("%d\n", ret); return 0; }
符号 与 符号的内容之间实现的是 完全替换, 符号后面有什么,那么就是什么,写的时候请注意一些符号,你替换过去是不是会多余。
#define 定义宏
宏有点类似于函数,ADD(a , b) == (a + b);
a 对应的是 x ,b 对应的是 y,宏的原理就是把传过去的 a and b 全部替换成相应的x 和 y
所以这里的 ADD(a,b) == (a + b * (a - b)),
宏在书写的时候应注意多加括号,避免替换后,与你想要的优先级不一样
类似于极限里面的等价无穷小,什么什么就是什么什么,注意优先级就行
#define ADD(x,y) (x + y*(x - y)); int main() { int a = 999; int b = 666; int ret = ADD(a, b)//替换后的样子(999 + 666 * (999 - 666)) printf("%d\n", ret); return 0; }
宏的要点
不管是定义 符号 还是 宏,都得 是先替换后运算。
如果宏的参数里有其他的符号会先 进行符号替换,再进行宏替换
宏也可以宏嵌套,也就是一个宏的参数可能是另一个宏,但是宏不能递归
字符串里面,不能调用宏
成
宏的参数可以是某个类型
#define ALG(type) type xx int main() { ALG(int); xx = 66; printf("%d\n",xx); return 0; }
宏与函数的对比
# and ## 运算符
# 将 宏 的一个参数转换为字符串表面量
#define aaa(x) #x int main() { printf(aaa(666\nljaflksd\n哈萨克开发阶段还是\n)); //aaa(666\nljaflksd\n哈萨克开发阶段还是\n) //就等于"666\nljaflksd\n哈萨克开发阶段还是\n" //等于printf("666\nljaflksd\n哈萨克开发阶段还是\n") return 0; }
## 宏里面参数转符号连接作用,把 int 和下划线粘贴在一起就变成了一个函数名
#define AAA(A) A A##_add(A x ,A y )\ {\ return (A)(x + y);\ } //函数创建 AAA(int)//等于int int_add(int x int y )\ {\ return (int)(x + y);\ } AAA(float)//等于float float_add(float x, float y)\ {\ return (float)(x + y); \ } int main() { int ret = int_add(5, 6); float retone = float_add(1.1f, 2.2f); printf("%d\n", ret); printf("%f\n", retone); return 0; }
条件编译
#undef 移除一个定义的符号
#ifdef 判断以一个符号是否被定义,为真执行语句为假则跳过 (判断是否有这个符号)
#define G int main() { #ifdef GHG printf("有定义\n"); #endif // GHG printf("hehe\n"); return 0; }
#endif 用来结束 #if 的判断,如果没有那么 #if 下面的所以代码将会被影响根本运行不了。
分支判断:与正常的分支语句道理相同,记得末尾 #endif
#ifndef 判断一个符号没有被定义,没有为真,定义了为假
文件包含
两种包含方式
#include<xxxxx.h> , 直接在标准头文件夹里搜索
这是我的头文件存放地,
想查自己的文件夹存放地,可用everthing随便搜索一个头文件然后打开路径,可能会有多个,注意位置
#include"xxxxx.h" , 先在工程文件夹里面搜索,搜不到再去标准头文件夹里搜索
同一个工程或项目,应避免重复包含头文件,否则只会增加代码量
避免方法
先定义一个符号,然后再在上面判断它没有被定义,因为当你第二次包含进来的时候,这个符号已经被定义,所后面都会被屏蔽掉
或者用#pragma once表示只被编译一次