C++预处理命令,c++预处理指令
一、预处理的由来:
在C语言的历史发展中,很多语言特性(尤其是语言的晦涩)都来源于C语言,预处理就是其中之一。从C语言继承C语言预处理器(C语言预处理器,Bjarne博士缩写为Cpp,不知道是不是C程序预处理器的缩写)。
二、常用预处理功能:
预处理器的主要作用是用预处理的内置函数替换一个资源。最常见的预处理包括文件包含、条件编译、布局控制和宏替换。
文件包含:#include是最常见的预处理,主要作为文件的引用来组合源程序文本。
编译条件:# if、# ifndef、# ifdef、# endif、# undef等。也是常见的预处理,主要是在编译时选择性的选择并注释掉一些指定的代码,从而实现版本控制的功能,防止文件的重复包含。
布局:#progma,这也是我们应用程序预处理的一个重要方面。它的主要功能是为编译器提供非常规的控制流信息。
宏替换:#define,这是最常见的用法。它可以定义各种函数,如符号常量、函数函数、重命名、字符串连接等。
三。预处理说明:
预处理指令的格式如下:
#定义令牌
#符号应该是该行的第一个非空字符。一般我们放在开头。如果一行指令放不下,可以用反斜杠“/”控制,例如:
#定义错误/
如果(错误)退出(1)
等于
#定义错误if(error) exit(1)
但是,为了美化,我们一般不会这么用。比较常见的方式如下:
# ifdef __BORLANDC__
if_true (is_convertible value,named _ template _ param _ base:value):
模板然后make_named_arg,Make _ key _ value:type Make;
#否则
枚举{ is _ named=is _ named _ parameter value:value };
typedef typename if _ true(is _ named):模板
然后make_named_arg,Make _ key _ value:type Make;
# endif
*******************************************************************
让我们来看看常见的预处理指令:
#定义宏定义
#undef取消宏
#包含文本包含
#ifdef编译已定义的宏
如果宏未定义,则#ifndef编译
#endif结束对编译块的控制。
#如果表达式非零,则编译代码
#else编译为其他预处理的剩余选项。
#elif这是#else和#if的组合选项
#line改变当前的行数和文件名
#error输出错误消息。
#pragma为编译器提供了非常规的控制流信息。
*******************************************************************
下面我们就来一一解释一下这些预处理。考虑到宏的重要性和复杂性,我们把它们放在了最后。
四。该文档包含说明:
这种预处理是最常见的使用方式,我们通常在编写程序时使用。最常见的用法是:
#包含iostream文件://stdlib.h
# include iostream . h file://Old-style stdlib . h
#include IO.hfile://用户定义的头文件
#包含./file . h file://UNIX下父目录中的头文件
# include /usr/local/file . h file://UNIX下的完整路径
#包含.//file.h file:在//dos下的父目录中的头文件
# include //usr//local//file . h file:在//dos下的完整路径
这里有两个地方需要注意:
1.我们用iostream还是iostream.h?
我们提倡用iostream而不是iostream.h为什么?我想你可能还记得,我已经给出了几个理由。这里我给大家大致解释一下:
首先,头文件在。h格式早在1998年9月就被标准委员会放弃了。我们应该跟上标准以适应时代的发展。
其次,iostream.h只支持窄字符集,而iostream支持窄/宽字符集。
况且标准对iostream做了很多改动,接口和实现都有变化。
最后,将iostream组件全部放入命名空间std中,以防止名称污染。
2.io.h和 io.h 的区别?
实际上,它们之间唯一的区别是不同的搜索路径:
对于#include io.h,编译器从标准库路径开始搜索。
对于#include io.h ,编译器从用户的工作路径开始搜索。
5.编译控制指令:
这些指令的主要目的是在编译时有选择地选择和注释掉一些指定的代码,从而实现版本控制的功能,防止文件的重复包含。
使用如下格式:
1、
#ifdef标识符
你的代码
#endif
如果标识符是一个定义的符号,你的代码将被编译;否则将被拒绝。
2、
#ifndef标识符
你的代码
#endif
如果标识符是未定义的符号,您的代码将被编译,否则将被拒绝。
3、
#if表达式
你的代码
#endif
如果expression非零,您的代码将被编译;否则将被拒绝。
4、
#ifdef标识符
您的代码1
#否则
您的代码2
#endif
如果标识符是一个定义的符号,你的代码1将被编译,否则你的代码2将被编译。
5、
#如果表达式1
您的代码1
#elif表达式2
您的代码2
#否则
您的代码3
#enif
如果epression1不为零,则编译代码1;否则,如果expression2为非零,则编译code2否则,编译您的代码3。
其他预编译指令
除了上面提到的常用编译指令,还有三种不太常用的编译指令:#line、#error和#pragma。接下来就简单说一下他们吧。
#line的语法如下:
#行号文件名
例如:#line 30 a.h其中文件名a.h可以省略。
这个命令可以改变当前的行号和文件名。比如上面的预处理命令,可以把当前行号改成30,文件名是A.H,乍一看好像没什么用。不过还是有用的,就是在编译编译器的时候用。我们知道编译器在编译C源代码的过程中会产生一些中间文件。通过这个指令,可以保证文件名是固定的,不会被这些中间文件替换,有利于分析。
#错误语法如下:
#错误信息
例如:
#ifndef UNIX
#错误该软件需要UNIX操作系统。
#endif
这个指令主要给出一个错误信息。在上面的例子中,如果它不在UNIX环境中,它会输出这个软件需要UNIX OS,然后诱导编译器终止。所以总之,这个指令的目的是在程序崩溃之前给出一些信息。
至于#pragma,我们已经在文章《解析#pragma指令》中介绍过了。这里再补充几句。#pragma是非统一的,它依赖于各种编译器生成器。例如,在SUN C编译器中:
//将name和val的起始地址调整为8字节的倍数
#progma align 8(名称,值)
char name[9];
双val
File://在程序执行的开始,调用函数MyFunction
#程序初始化(MyFunction)
预定义标识符
为了处理一些有用的信息,预处理定义了一些预处理标识符。虽然各种编译器的预处理标识符不同,但都处理以下四种:
__FILE__正在编译的文件的名称。
__LINE__正在编译的文件的行号。
__DATE__编译时间的日期字符串,例如:“2000年12月25日”
__TIME__编译时的时间字符串,例如:“12:30:55”
示例:cout 文件是:“__FILE__ ”!这几行是:“_ _ LINE _ _ endl
预处理何去何从?
在文章《浅析C++里面的宏》中,我们提到了如何替换#include预处理指令,这里就不一一讨论了。
c没有提供#include的替代形式,但是namespace提供了一种范围机制,可以以某种方式支持组合。使用它可以改进#include的行为,但是我们仍然不能替换#include。
#progma应该被视为可选的预处理指令。按照C之父Bjarne的说法是:“#progma被过度地、经常地用于将语言的语义变形隐藏到编译系统中,或者提供具有特殊语义和笨拙语法的语言扩展。”
对于#ifdef,我们还是无可奈何。即使我们使用if语句和常量表达式,仍然不足以取代它,因为if语句的主体必须语法正确,并且满足类检查,即使它在永远不会执行的分支中。
最后,我们以Bjarne博士的话结束:“最后,在多年之后,将Cpp流放刀程序开发环境与其他额外的语言工具放在一起,这就是她应该呆的地方。”
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。