1、宏定义
格式:
#define 标识符(也称为宏名) 替换列表
例如;
#define PI 3.14
以上代码就是定义了一个宏。 宏的名称为PI, 我们在使用的时候,会在编译预处理时,将代码中的PI替换为3.14
注意: 没有 分号
</pre><pre name="code" class="cpp"> printf("pi = %f \n", PI);
//结果为 pi = 3.14
其实,就是进行了简单的替换而已。那么我们可以利用这个特性,进行代码混淆。
2、可以进行代码混淆
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define _ int
#define __ main
#define ___ (
#define ____ )
#define _____ {
#define ______ }
#define _______ printf("Hello C\n");
#define _________ return 0;
#define ___________ system("pause");
_ __ ___ ____
_____
_______
___________
_________
______
运行效果为:
3、带参数的宏
格式:
#define 标识符(参数列表) 替换列表
例如:
<span style="white-space:pre"> </span>#define MAX(a,b) ((a)>(b)?(a):(b))
<span style="white-space:pre"> int nNum = MAX(3,4); </span>// 会替换为 int nNum = ((3)>(4) ? (3) : (4) )
注意:每个参数都要单独的加上小括号(),否则会出现一些问题
4、当宏定义一个很长的字符串的时候
<span style="white-space:pre"> </span>#define STRTING "andfdsafdsafdsafdsafdsafdsfdsafdasfdsafdafdsafdsafasdfffffffffffffffffffffffffffffffffffffffffffffffffff"
如果我们这么去定义,未尝不可,但是要是1w个字符呢?这样定义就有待商榷了,加上从风格来说也不是很好。
那遇到该问题我们如何解决------------------使用 \ 即可, 在每一个换行的时候加上一个 \
<span style="white-space:pre"> </span>#define STRTING "andfdsafdsafdsafdsafdsafdsfdsafdasfdsaf"\
<span style="white-space:pre"> </span> "dafdsafdsafasdfffffffffffffffffffffffff"\
<span style="white-space:pre"> </span> "ffffffffffffffffffffffffff"
5、取消宏
<span style="white-space:pre"> </span>格式:<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>#<span style="color:#ff6666;">undef 宏名</span>
//会自动添加上双引号
#define <span style="color:#ff0000;">mprint(m) </span> printf("%s = %d \n", #m, m)
int main()
{
int nNumA = 12;
#<span style="color:#ff6666;">undef mprint(m) //取消宏定义 此行一下 都不能再使用 </span><span style="color: rgb(255, 102, 102); font-family: Arial, Helvetica, sans-serif;">mprint(m) 宏</span><span style="color:#ff6666;">
</span>
//mprint(nNumA); //此时 会报错
system("pause");
return 0;
}
6、宏定义中 # 的作用,会将使用的参数自动添加上 双引号。
<span style="white-space:pre"> </span>int nNumA = 12;
我们想输出的效果为 nNumA = 12;
如果直接使用
<span style="white-space:pre"> </span>printf("%s = %d \n", nNumA, nNumA);
这样是实现不了我们想要的效果的,接下来 我们使用 宏定义
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
//会自动添加上双引号
#define mprint(m) printf("%s = %d \n", #m, m)
int main()
{
int nNumA = 12;
//我们想输出的效果为 nNumA = 12;
//printf("%s = %d \n", nNumA, nNumA); //这样是实现不了我们想要的效果的
mprint(nNumA);
system("pause");
return 0;
}
效果图
7、系统预定义的宏
在C语言中收录了一些有用的宏,这些宏是提供当前编译信息的。
__LINE__ 被编译文件的行数(整型)
__FILE__ 被编译文件的名字 (字符型)
__DATE__ 编译日期 (字符型)
__TIME__ 编译时间 (字符型)
__STDC__ 如果编译器接受标准C,那么值为1. (整型)
8、条件编译
有三种情况
如果标识符被定义过 #ifdef
<span style="white-space:pre"> </span>#ifdef 标识符
<span style="white-space:pre"> </span>/*程序段1*/
<span style="white-space:pre"> </span>#else
<span style="white-space:pre"> </span>/*程序段2*/
<span style="white-space:pre"> </span>#endif
如果标识符未被定义过 #ifndef ----里面有个n
<span> </span>#ifndef 标识符
<span> </span>/*程序段1*/
<span> </span>#else
<span> </span>/*程序段2*/
<span> </span>#endif
根据表达式判定
<span> </span><pre name="code" class="cpp"><span> </span>#if 表达式
<span> </span>/*程序段1*/
<span> </span>#else
<span> </span>/*程序段2*/
<span> </span>#endif