预处理指令

  1. 什么是预处理指令

程序设计语言的预处理的概念:在编译之前进行的处理

预处理指令是我们写在程序代码中的给预处理器(preprocessor)的 命令,而不是程序本身的语句。预处理器在我们编译一个C++程序时由编译器自动执行,它负责控制对程序代码的第一次验证和消化。

 

特点:

所有这些指令必须写在单独的一行中,由#开头,它们不需要加结尾的分号;

.  c++的预处理指令

c/c++语言的预处理主要有一下几个方面的内容:

 1.宏定义:#define#undef

 2.文件包含#include

 3.条件编译:#ifdef、#ifndef、#if、 #endif、#else、#elif

 4.布局控制:#error#pragma

 预处理命令以符号“#”开头。

 

详解

使用说明&常见误区

#define 

宏定义是简单的替换,即将宏名替换为对应的字符串

a.简单的替换(#define <宏名> <字符串>

#define MAX 100

  在编译前,所有使用宏名MAX的地方都会被替换为100
b.
带参数的宏替换(#define <宏名> (<参数表>) <宏体>

#define MaxNum(a,b) a>b?a:b

     可以用来宏定义函数

 

使用宏替换常量,例如在TCP编程中端口号

很方便程序的修改,而且将常量变成了有意义的字符,也提高了程序的可读性

#define N  2+2

 

对于语句:

int a=N*N

a的值为8,实质上N*N等于2+2*2+2,而非4*4,在替换过程中只是文本替换,而不会有计算

#undef

作用与#define相反,取消对传入的参数的宏定义

#define MaxNum(a,b) a>b?a:b

#undef MaxNum

 

此时就不能在程序中使用宏名MaxNum

#ifdef, #ifndef, #if, #endif, #else, #elif

个人觉得这些指令可以分为同一类,都是在某种条件下忽略程序的某部分代码

 

#ifdef MAX

// code

#endif

只有在MAX已定义的情况下,code所代表的部分代码才会被编译器编译

 

#if MAX>200

      code

#endif

只有在MAX>200的情况下,code所代表的部分代码才会被编译器编译

 

#else

#elif=#else if

 

 

在开发可移植、多平台的程序时经常使用

#error

使用格式

#error [用户自定义的错误消息]

当预处理器处理到#error命令时将停止编译并输出用户自定义的错误消息

eg

#include <iostream>

using namespace std;

 

#ifndef MAX

#error not define MAX

#endif

 

int main(int argc, char* argv[])

{

cout << "This is a test!" << endl;

return 0;

}

此程序在编译时会输出error C1189: #error :  not define MAX        

编译停止

 

#include

        对任何一个c/c++程序员来说,这都是一个非常熟悉的命令。当预处理器找到一个#include 指令时,它用指定文件的全部内容替换这条语句。声明包含一个文件有两种方式:

#include "file"

#include <file>

         两种表达的唯一区别是编译器应该在什么路经下寻找指定的文件。第一种情况下,文件名被写在双引号中,编译器首先在包含这条指令的文件所在的目录下进行寻找,如果找不到指定文件,编译器再到被配置的默认路径下(也就是标准头文件路径下)进行寻找。

         如果文件名是在尖括号 <> 中,编译器会直接到默认标准头文件路径下寻找。

    一般来说,如果是自定义头文件会使用"",而官方的头文件用<>

未防止头文件多次引用:

方法一:

egtest.h

#ifndef TEST_H

#define TEST_H

...... // 一些声明语句

#endif

该方法依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况

 

方式二:

#pragma once

... ... // 一些声明语句

#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。

 

一般来说,使用第一种方法较多,因为二种方法可能受编译器限制,而第二种是语言特性,不受编译器限制,可移植性较好

#pragma

         这条指令可以说是所有预处理指令中最复杂的一个指令

         作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。所以可能有些用法会出现可移植性差的情况

         使用格式:

          #pragma Para     其中Para 为参数

 

常见用法:

#pragma once

只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,不过可移植性较差

 

#pragma message("消息文本")

当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值