目录
今天我们主要学习深度理解条件编译,和其他预处理指令相关内容
希望大家今天也要心情愉悦哦。
深入理解条件编译
1.条件编译的使用
1.1 #ifdef 和 #ifndef区别。
1.2 #if 和 #ifdef的区别
1.3 #if defined(宏)实现 #ifdef功能
1.4可以使用逻辑的形式同时判断两个宏的成立,来进一步判断条件编译的结果
1.5 条件编译可以嵌套吗?
1.6 剩下的多分支和单分支的实现在上一篇博客已经说过不在赘述。
2. 为什么要有条件编译?
深入理解文件包含
2.1 为什么这个东西可以避免头文件重复包含?
2.2文件重复包含的后果。
其他预处理指令讲解
3.1 #error 和 #pragma message ()的对比讲解
3.2 #pragme 相关的预处理指令
3.3 #line
关于 # 和 ## 的例子
#的作用:是把参数的符号转化为 "字符串"。
##的作用:把宏的参数组合形成新的符号。
下期预告:
下期主要讲解 指针相关 内容
下期更精彩哦~~~
条件编译在上一篇博客已经讲过了,但是因为有些东西还是不够细致,所以今天做个补充。
上一篇博客说了写使用方法但是还有些方法没有说,下面一起看一些例子吧。
这两个条件刚好是相反的,前者是的判断宏是否被定义,后者是对前者结果进行逻辑取反
#define MAX
int main()
{
#ifndef MAX
printf("MAX被定义\n");
#endif
#ifdef MAX
printf("MAX被定义\n");
#endif
return 0;
}
这通过产生了 .i 文件的形式,进行直观表达。
#if 是判断后面宏的逻辑上的真假 #ifdef只是判断宏的定义与否
#define MAX 0
int main()
{
#if MAX
printf("MAX是真\n");
#else
printf("MAX是假\n");
#endif
#ifdef MAX
printf("MAX已被定义\n");
#endif
return 0;
}
这里可以看出,虽然MAX的值是0,但是MAX是被定义的(即使宏为空,依然也是被定义的)
看下代码,理解下#if后必须是常量表达式,和模拟实现#ifdef。
#define MAX
int main()
{
#if defined(MAX)
printf("MAX已定义\n");
#endif
#ifdef MAX
printf("2.MAX已定义\n");
#endif
#if MAX //因为MAX没有值,所以报错
printf("MAX为假\n");
#endif
return 0;
}
可以看出来#if defined模拟实现#ifdef的效果,下面的那个#if只是起对比作用
同理,实现#ifndef的话使用 #if !defined就可以了(本质就是对值进行逻辑取反)
如果同时有两个宏有需要判定呢?该怎么办呢?
看例子:
#define MAX 1
#define MIN 0
int main()
{
#if (defined(MIN) && defined(MAX))
printf("MAX,MIN同时被定义");
#else
printf("未全部定义\n");
#endif
return 0;
}
这样就可以同时判断两个宏是否被定义的情况了。(同理,逻辑或成立,逻辑与也是可以的,逻辑取反也是可以的,自己动手试试呀)
就像是if语句一样是可以嵌套的。不废话,看例子:
#define MAX
#define MIN
int main()
{
#if defined(MAX)
#if defined(MIN)
printf("MIN定义\n");
#endif
printf("MAX定义\n");
#else
printf("未定义\n");
#endif
return 0;
}
这样来看,好像一个if语句的嵌套,每个#if defined(宏)是判断表达式要不要执行。(同理,你可以看下不同的宏,是否定义带来的不同的条件编译,产生的不同的结果)
单分支多分支条件编译
通过裁剪代码,快速实现某种目的(比如一些功能的裁剪,和一份代码的免费版和收费版维护,和一些代码的跨平台性)
首先这是条件编译的知识,
第一行是判断 __TEST_H__ 这个宏有没有被定义,
第二行是定义__TEST_H__ (把这个宏定义)
第三行是头文件内容
第四行是#endif条件编译结束。
综上所述,这个东西每一个头文件都需要这样写。
所以我们推荐使用 #pragma once 来防止头文件被引用。
我们要知道文件重复包含,最大的后果就是很多声明文件重复了,很多的东西重复了,就导致代码的编译效率低下。
你看,如果头文件被重复包含,那么就会导致多次声明,虽然没有出错,但是在编译效率上降低了。
#error就是让编译器打印一些字符,是以 "错误" 的方式
例 :
这样打印的消息是不可以通过编译的,所以叫 "错误" 的方式。
而#pragma message ()则是警告或者叫"提示"的方式。
他们都可以用在条件编译中,#error是错误级别的,#pragma message ()是提示级别的。
#pragme once防止头文件重复包含。
#pragme pack()改变默认对齐数。
#pragme warning(4996)是VS下,接口型警告,常见的是scanf的警告。
修改当前的文件名和行数。
看例子:
看个例子,把数字转化为字符输出。
#define NUM(s) #s
int main()
{
printf("π:"NUM(3.1415926)"\n");
return 0;
}
这样就可以把参数转化为字符,输出了。
看个例子 ,用宏求一个数的科学计数法的值
这样不太直观,我们看下预处理后的结果吧。
这样看是不是就是浮点数的科学计数法了。