收藏 分享(赏)

预处理 命令与宏.doc

上传人:精品资料 文档编号:8594842 上传时间:2019-07-04 格式:DOC 页数:4 大小:17.50KB
下载 相关 举报
预处理 命令与宏.doc_第1页
第1页 / 共4页
预处理 命令与宏.doc_第2页
第2页 / 共4页
预处理 命令与宏.doc_第3页
第3页 / 共4页
预处理 命令与宏.doc_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

1、预处理命令与宏刚接触到MFC编程的人往往会被 MFC向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具。使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能。一个经典的例子使用预处理与宏定义最经典的例子莫过于加在一个头文件中以避免头文件被两次编译。试想这种的情况,有一个文件headerfile.h它被包含在headerfile1.h中,同时在headerfile2.h中也被包含了,现在有一个CPP文件,implement.cpp包含了headerfile1.h和headerfile2.h:#include“headerfile1.h“#incl

2、ude“headerfile2.h“假设headerfile.h中定义了一个全局变量iglobal.intiglobal;在编译的时候编译器两次编译headerfile,也就会发现iglobal被定义了两次,这时就会发生变量重定义的编译错误。传统的解决办法是使用#ifdef以及#endif来避免头文件的重复编译,在上面的例子中,只需要加上这么几行:#ifndefsmartnose_2002_6_21_headerfile_h#definesmartnose_2002_6_21_headerfile_hintiglobal;#endif仔细的考虑上面的宏定义,会发现当编译器编译过一次header

3、file.h以后,smartnose_2002_6_21_headerfile_h这个宏就被定义了,以后对headerfile.h的编译都会跳过intiglobal这一行。当然smartnose_2002_6_21_headerfile_h这个宏是可以任意定义的,但是这个宏本身不能和其它文件中定义的宏重复,所以MFC在自动生成的文件中总是使用一个随机产生的长度非常长的宏,但我觉得这没有必要,我建议在这个宏中加入一些有意义的信息,比方作者,文件名,文件创建时间等等,因为我们有时候会忘记在注释中加入这些信息。在VC.Net中我们不会再看见这些宏定义了,因为在这里会普遍使用一个预处理指令:#prag

4、maonce只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。源代码版本控制当我们为许多平台开发多个版本的时候预编译指令和宏定义也能够帮我们的忙。假设我们现在为WINDOWS和LINUX开发了一套软件,由于这两种系统的不同,我们不得不在程序控制源代码的版本。比方内存的分配,我们可以在LINUX上使用标准C的malloc函数,但是我们希望在WINDOWS上使用HeapAllocAPI.下面的代码演示了这种情况:main()#ifdef_WINDOWS_PLATFORMHeapAlloc(5);#elsemalloc

5、(5);#endif当我们在WINDOWS平台上编译此程序的时候,只需要定义_WINDOWS_PLATFORM这个宏,那么HeapAlloc这条语句就能够起作用了。这样就能够让我们在同一个文件中为不同的平台实现不同版本的代码,同时保持程序的良好结构。在许多情况下,我们还可以为一个方法使用不同的算法,然后用宏定义来针对不同的情况选择其中的一个进行编译。这在MFC应用程序中是使用得最多的。最明显的就是文件中经常存在的#ifdef_DEBUG。somecode#endif这样的代码,这些代码在应用程序的调试版(DEBUG)中会发挥其作用。#Pragma指令在所有的预处理指令中,#Pragma指令可能

6、是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。其格式一般为#PragmaPara其中Para为参数,下面来看一些常用的参数。message参数。Message参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:#Pragmamessage(“消息文本“)当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义

7、了_X86这个宏可以用下面的方法#ifdef_X86#Pragmamessage(“_X86macroactivated!“)#endif当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_X86macroactivated!“。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。另一个使用得比较多的pragma参数是code_seg.格式如:#pragmacode_seg(“section-name“,“section-class“)它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。最后一个比较常用的就是上面所说的#pragmaonce指

8、令了。VC预定义的宏在VC中有一类宏并不是由用户用#define语句定义的,而是编译器本身就能够识别它们。这些宏的作用也是相当大的。让我们来看第一个,也是MFC中使用得最频繁的一个:_FILE_.当编译器遇到这个宏时就把它展开成当前被编译文件的文件名。好了,我们马上就可以想到可以用它来做什么,当应用程序发生错误时,我们可以报告这个错误发生的程序代码在哪个文件里,比方在文件test.cpp中有这样的代码:trychar*p=new(char10);catch(CException*e)TRACE(“thereisanerrorinfile:%s“,_FILE_);在程序运行的时候,如果内存分配出

9、现了错误,那么在调试窗口中会出现thereisanerrorinfile:test.cpp这句话,当然,我们还可以把这个错误信息显示在别的地方。如果我们还能够记录错误发生在哪一行就好了,幸运的是,与_FILE_宏定义一样,还有一个宏记录了当前代码所在的行数,这个宏是_LINE_.使用上面的两个宏,我们可以写出一个类似于VC提供的ASSERT语句。下面是方法#defineMyAssert(x)if(!(x)MessageBox(_FILE_,_LINE_,NULL,MB_OK);我们在应用程序中可以象使用ASSERT语句一样使用它,在错误发生时,它会弹出一个对话框,其标题和内容告诉了我们错误发生的文件和代码行号,方便我们的调试,这对于不能使用ASSERT语句的项目来说是非常有用的。除了这两个宏以外,还有记录编译时间的_TIME_,记录日期的_DATE_,以及记录文件修改时间的_TIMESTAMP_宏。使用这些预定义的宏,我们几乎可以生成和VC能够生成的一样完整的源代码信息报表。结论翻开MFC和Linux的源代码,宏定义几乎占据了半边天,消息映射,队列操作,平台移植,版本管理,甚至内核模块的拆卸安装都用宏定义完成。毫不夸张的说,有些文件甚至就只能看见宏定义。所以学习宏定义,熟练的使用宏定义对于学习C语言乃至VC都是非常关键的。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报