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