- 什么是预处理指令
程序设计语言的预处理的概念:在编译之前进行的处理
预处理指令是我们写在程序代码中的给预处理器(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 #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> 两种表达的唯一区别是编译器应该在什么路经下寻找指定的文件。第一种情况下,文件名被写在双引号中,编译器首先在包含这条指令的文件所在的目录下进行寻找,如果找不到指定文件,编译器再到被配置的默认路径下(也就是标准头文件路径下)进行寻找。 如果文件名是在尖括号 <> 中,编译器会直接到默认标准头文件路径下寻找。 一般来说,如果是自定义头文件会使用"",而官方的头文件用<> | 未防止头文件多次引用: 方法一: eg:test.h #ifndef TEST_H #define TEST_H ...... // 一些声明语句 #endif 该方法依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况
方式二: #pragma once ... ... // 一些声明语句 #pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
一般来说,使用第一种方法较多,因为二种方法可能受编译器限制,而第二种是语言特性,不受编译器限制,可移植性较好 |
#pragma | 这条指令可以说是所有预处理指令中最复杂的一个指令 作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。所以可能有些用法会出现可移植性差的情况 使用格式: #pragma Para 其中Para 为参数
常见用法: #pragma once 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,不过可移植性较差
#pragma message("消息文本") 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
|
|