条件编译,是让编译器在条件满足时才进行编译,否则编译器就会忽略。
条件编译块,其语法结构为:
#if [必须]
#elif [可选]
#else [可选]
#endif [必须]
另外下面的形式是等价的:
#ifdef (identifer)<==> #if defined (identifer)
#ifndef (identifer) <==> #if !defined (identifer)
其作用依赖于你的写法和意图,例如:
(1)防止头文件被重复编译,在头文件windows.h中我们看到一个最大的条件编译块:
#ifndef _WINDOWS_ //位于头文件有效代码最顶部
#define _WINDOWS_
//...
#endif // 位于头文件尾部
那么如果你的工程实现文件中重复包含了windows.h也不会导致问题,因为windows.h在被第一次编译的时候就定义了_WINDOWS_ 标识,下次编译器不会再编译条件编译块之间的代码了,因为条件为假。
(2)检测CPU类型
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
#define _X86_ // Intel公司提供的 X86系列CPU
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
#define _AMD64_ // ADM公司提供的CPU
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_M68K)
#define _68K_ // 苹果电脑通常使用一种CPU
#endif
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_MPPC)
#define _MPPC_ // 苹果电脑通常使用另一种CPU
#endif
(3)检测硬件平台
#ifndef _MAC
#if defined(_68K_) || defined(_MPPC_) // 如果使用了这两种类型的CPU
#define _MAC // 则为苹果电脑的硬件平台
#endif
#endif
当然条件编译块的用途实在是太多了,你当然可以把它嵌入你的源代码中,控制编译器有选择地编译,而不是仅仅在头文件中使用。
需要注意的是:
如果定义了_MAC标识,是指的苹果电脑的硬件平台,而不是苹果操作系统。事实上,苹果电脑上现在也可以装windows操作系统。
要知道编译器对不同的硬件平台(主要指CPU类型)生成的机器码是不同的,所以界定硬件平台是重要的,但是由于我们基本上都是使用的X86系列CPU,所以实际也不需要太关心这个。
头文件中的条件编译是把头文件中的所有东西都包含进去还是仅仅把函数申明包含进去啊?
比如:
#define NEWSIZE 1000
#define NULL 0
#ifndef NEW_H_H
#define NEW_H_H
char *new(int n);
#endif
是这样写还是:
#ifndef NEW_H_H
#define NEW_H_H
#define NEWSIZE 1000
#define NULL 0
char *new(int n);
#endif
第二种加上安全警戒比较好 避免重复声明
总结了解决multiple definition of的方法:
问题原因:
当多个文件包含同一个头文件时,并且你的.H里面没有加上条件编译
#ifndef TEST_H
#define TEST_H
#endif
就会独立的解释,然后生成每个文件生成独立的标示符.在编译器连接时,就会将工程中所有的符号整合在一起,,文件中有重名变量,于是就出现了重复定义的错误.
方法1:
给每一个头文件加上条件编译,避免该文件被多次引用时被多次解释,这是个应该是习惯.这个方法会解决大部分低级问题.
方法2:
当方法1无效时,可以把所有的全局变量放入一个头文件 global.h (名字随意起,但要加条件编译)中,每一个变量前面加extern,声明一下这些变量将在其它文件中定义. 然后建立一个和头文件名字对应的.c or .cpp文件 如global.c.在里面声明所有的全局变量.例如:void(*Handl_Display)();
然后,让涉及到全局变量的文件include ”global.h“.这样编译时,会先对global.c编译生成一个global.o ,然后再和其它文件的.o链接生成可执行文件.
方法3:
懒人方法,在所有的全局变量前加上static ,声明成静止变量.也能解决问题.