这两天来忙活ucos-II在PIC18fxxx系列上的移植。在编译的时候老出现变量被多重定义的错误。花费了一天的功夫才成功编译通过,错误何在??就是因为没有搞明白条件编译的原理,二是对mcc18编译器的特点无知。下面学习条件编译方面的知识:
【例6.6】使用条件编译命令解决由于文件包含而出现的变量重名问题。
设有头文件exemple6_6.h,其内容如下:
# define R 6
float volume;
源文件exemple6_6.cpp的内容如下:
# include <iostream.h>
# include " exemple6_6.h"
# define PI 3.14159
# define R 6
# define AREA R*R*PI
float volume;
void main(void)
{ volume=4*PI*R*R*R /3;
cout<<"圆的面积="<<AREA<<endl;
cout<<"圆球体积="<<volume<<endl;
}
该题编译时出现,volume变量被重复定义的错误。事实上,经预编译后,将头文件包含在源文件中,因此,预编译后的源文件为:
# include <iostream.h>
# define R 6
float volume;
# define PI 3.14159
# define R 6
# define AREA R*R*PI
float volume;
void main(void)
{ volume=4*PI*R*R*R /3;
cout<<"圆的面积="<<AREA<<endl;
cout<<"圆球体积="<<volume<<endl;
}
显然,表示圆球体积的变量volude被重复定义了二次,表示圆半径的宏名R也被重复定义了二次。为了解决写在两个不同文件中可能出现变量名重名的问题,可使用条件编译命令。采用条件编译命令后的头文件exemple6_6.h修改如下:
#ifndef _EX_ H
# define _EX_ H //2
# define R 6 //3
float volume; //4
# endif
采用条件编译命令后的源文件exemple6_6.cpp修改如下:
# include <iostream.h>
# include "exemple6_6.h"
#ifndef _EX_ H
# define _EX_ H //4
# define R 6 //5
float volume; //6
# endif
# define PI 3.14159
# define AREA R*R*PI
void main(void)
{ volume=4*PI*R*R*R /3;
cout<<"圆的面积="<<AREA<<endl;
cout<<"圆球体积="<<volume<<endl;
}
程序执行后输出:
圆的面积=113.097
圆球体积=904.778
程序在预编译头文件时,先判断是否定义过标识符_EX_ H,若没有定义过,则执行第2、3、4行语句,定义标识符_EX_ H,定义全局变量volume与宏名R,否则不执行2、3、4行语句。编译源文件时,同样先判断是否定义过标识符_EX_ H,若没有定义过,则执行第4、5、6行语句,定义标识符_EX_ H,定义全局变量volume与宏名R,否则不执行4、5、6行语句,不定义全局变量volume与宏名R。由于头文件先编译,所以在头文件中已定义了标识符_EX_ H、全局变量volume与宏名R,所以编译源文件时,#ifndef _EX_ H为假,不再重复定义全局变量volume与宏名R。避免变量重名产生的编译错误。这种用条件编译命令解决由多个用户编写多文件程序中出现变量重名问题是非常有效的。
另链接C语言编译全过程剖析:
http://www.yuanma.org/data/2009/0506/article_3647.htm