目录
预处理(预编译)详解
预定义符号
__FILE__ 这个代码所在的这个文件的名称
__LINE__ 文件当前的行号
__DATE__ 文件被编译的日期
__TIME__ 文件被编译的时间
__STDC__ 如果编译器遵循ANSCII,其值为1,否则未定义
可以利用这个写日志文件
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 0 };
FILE* pf = fopen("log.txt", "w");
for (i = 0; i < 10; i++)
{
arr[i] = i;
fprintf(pf, "file:%s line:%d date:%s time:%s i=%d\n",
__FILE__, __LINE__, __DATE__, __TIME__, i);
}
fclose(pf);
pf = NULL;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
也可以打印函数名字
arr[i] = i;
fprintf(pf, "file:%s line:%d date:%s time:%s i=%d\n",
__FILE__, __LINE__, __DATE__, __TIME__, i);
printf("%s\n", __FUNCTION__);
这样就能打印出main。
__STDC__需要遵循ANSCII才可以使用
#define
是一种预处理指令。井号开头的都是预处理指令
#define name stuff(内容) 这里也就展现出自由性高
#define do_forever for(;;)
int main()
{
do_forever;
return 0;
}
这样也就死循环了。如果forever后面没有; 也就是do_forever return 0; 那么就不会死循环,执行完for语句后,就会return 0,程序结束。
#define MAX 100后面不能加分号,比如
#include <stdio.h>
#define MAX 100
int main()
{
int a = MAX;
printf("%d\n", 100);
return 0;
}
MAX后面的都是内容,所以如果是100; 那么MAX就会在main函数体内被传换成100; 容易出问题。
#define 定义宏
#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏或定义宏。
宏的申明方式:
#define name(parament-list) stuff 其中的parament-list是一个由逗号隔开的符号表,它们可能出现在stuff中。参数列表的左括号必须与name紧邻, 如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
#include <stdio.h>
#define SQUARE(X) X*X
int main()
{
int ret = SQUARE(5);
printf("%d\n", ret);
return 0;
}
这样ret就是25.SQUARE就是宏。但是这样的定义有问题
#define SQUARE(X) X*X
int main()
{
int ret = SQUARE(5 + 1);
printf("%d\n", ret);
return 0;
}
如果这样的代码,结果是11。宏的实现是替换而来的,x会被替换为5+1,那么这个计算就是5+1*5+1,也就是11。如果想打印36,那么把X变成(X)就好,#define SQUARE(X) (X)*(X),因为*的优先级比+高。
#define DOUBLE(X) X+X
int main()
{
int a = 5;
int ret = 10 * DOUBLE(a);
printf("%d\n", ret);
return 0;
}
这样仍然是替换,10*5+5,所以是55。
#define替换规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
1、在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换
#define MAX 5
#define DOUBLE(X) ((X)+(X))
int ret = 10 * DOUBLE(MAX);
那就先把MAX替换完
2、替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。
3、最后,再次对结果文件进行扫描,看看它是否报刊任何由#define定义的符号。如果是,就重复上述处理过程。
注意:
1、宏参数和#define定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归
2、当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
printf("MAX = %d\n", MAX); 像这样,只有单独的那个MAX会被替换。
#和##
int main()
{
int a = 10;
printf("the value of a is %d\n", a);
return 0;
}
把这个printf换成一个函数
void print(int a)
{
printf("the value of a is %d\n", a);
}
int main()
{
int a = 10;
print(a);
return 0;
}
还是一样的结果,现在添加另一个变量
void print(int a)
{
printf("the value of a is %d\n", a);
}
int main()
{
int a = 10;
int b = 20;
print(a);
print(b);
return 0;
}
但是这样就会变成the value of a is 20;如果想the value of b is 20。如果想传b还是a都能成输出正确的内容,可以用宏,用宏前先写一个东西
int main()
{
printf("hello world\n");
printf("hello" "world\n");
printf("hel" "lo" "world\n");
}
无论怎样拆分,都会打印一样的内容,两三个字符串都会拼在一起打印。再看宏
#define PRINT(X) printf("the value of X is %d\n", X)
int main()
{
int a = 10;
int b = 20;
PRINT(a);
PRINT(b);
return 0;
}
这样还是会错误,会一直打印有X
#define PRINT(X) printf("the value of "#X" is %d\n", X)
X左右的两个引号,使the value of 和is %d变成两个字符串,而#X也是变成了字符串
使用#,把一个宏参数变成对应的字符串
##可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符
#define CAT(X, Y) X##Y
int main()
{
int a3 = 47;
printf("%d\n", CAT(a, 3));
return 0;
}
这样就是连起来变成a3,也就打印出来47。代码在预处理后,就会直接变成a3。
结束。