`

C++中的预编译指令

    博客分类:
  • C++
阅读更多
C++预处理指令

#include

#define

#undef

#pragma

#import

#error

#line

#ifdef

#ifndef

#if

#else

#elif

#endif



宏以#起始 不以;结束



一.        #include 文件包含

预编译期发现#include后,将会寻找HeaderName并把其包含到当前文件中

EG:#include <HeaderName>

常见形式:

#include <iostream.h>          //

#include <iostream>            //

#include "iostream"            //

#include "TestHeader.h"        //

#include "..\TestHeader.h"     //



1.      #include <iostream.h>和#include <iostream>区别

#include <iostream.h>是老规范,现已经抛弃

#include <iostream>是新规范,使用名称空间避免名称冲突。即将所有的定义放在了一个名称空间std中



2.      #include <iostream>和#include "iostream"区别

#include <iostream>直接在系统的路径下查找此头文件。多是系统的头文件

#include "iostream"首先在当前目录查找,如果没有找到再到系统目录查找



3.      头文件的多次包含问题

编译器对每个文件只编译一次生成一份机器代码.obj,如果在多个地方包含了同一个头文件,则会出现多次包含的错误,即试图让编译器将此文件编译多次生成多份机器代码。

预编译保护解决此问题。



二.        #define  #undef 宏替换

#define 宏 宏主体

宏展开:在代码中出现宏,会用宏实体代替宏



#define 定义常量、函数宏

#undef  结束常量、函数宏定义



1.    常量宏

常量宏:是最常见的一种形式。即使用一个宏代替实际的常量,如数据、字符、字符串常量等

#define CONST_VAL 2

#define MEG_EG "Test Macro!"

#define CHARACTOR_EG 'M'



注:

(1)    可以使用#undef结束常量宏定义,结束宏定义宏此宏不能再次使用。即时这个宏实际不存在,使用#undef结束宏定义也不是错误,相反在定义一个宏时如果不确定其是否已经定义可以先使用#undef结束其定义,然后重新定义

(2)    可以多次定义同一个宏



2.    函数宏

函数宏:外形和作用都与函数类似并且有参数输入

#define MAX(x, y) ( (x>y)?x:y )



注:

(1)    定义函数宏是将宏体都用一个“( ) “括起来。

#define MAX(x, y) ( (x>y)?x:y )

cout << "MAX = " << MAX(1,2) << endl;  //正确



#define MAX(x, y) (x>y)?x:y

cout << "MAX = " << MAX(1,2) << endl;  //错误。将<<和宏混淆

(2)    通常将函数宏第一为一行,但可以使用“\“定义多行宏函数

           #define MAX(x, y) ( (x>y)?\

                       x:y )

(3)    可以使用#undef结束函数宏定义

    #undef MAX(x, y)和#undef MAX都可以

(4)    宏函数产生内联代码,形式上等同与inline函数,当没有inline函数安全

(5)    宏函数不检查输入的参数(相比inline函数不安全)

(6)    宏函数没有inline函数效率高

  

3.    #运算符

#运算符可以在一个字符串中输入宏参数,使得一个字符串可以包含某个参数

EG:

#define STR_A(A) ( printf("STR_A(A) A = "#A" ") )

#define STR_B(B) ( "STR_B(B) B = "#B" " )

#define STR_C(CA, CB) ( "STR_C(CA, CB) C = "#CA"  "#CB" " )

        STR_A(1);

        cout << endl;

        cout << STR_B(2) << endl;

        cout << STR_B(B) << endl;

        cout << STR_C(CA, CB) << endl;

       

        string strB = "strB ";

        strB += " + ";

        strB += STR_B(B);

cout << "strB + Macro STR_B = " << strB << endl;

  

4.    ##运算符

  ##运算符用于创建变化的变量,即使用宏参数创建变化的变量

  

EG:

       #define VARIAVLE_NAME(N) ( n##N )

        int VARIAVLE_NAME(IntA) = 1;                // int nIntA

        int VARIAVLE_NAME(1) = 1;                   // int n1

        int VARIAVLE_NAME(2) = 1;                   // int n2

        cout << "nIntA = " << nIntA << endl;

        cout << "n" << 1 <<" = " << VARIAVLE_NAME(1) << endl;

        cout << "n" << 2 <<" = " << VARIAVLE_NAME(2) << endl;

       

        double VARIAVLE_NAME(DoubleA) = 1.1;

        cout << "nDoubleA = " << nDoubleA << endl;

      

三.        #pragma

其格式一般为: #pragma para

其中para 为参数,下面来看一些常用的参数。

(1)   #pragma once

多次包含的保护。只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。



等价于:(此为C/C++标准 通用性更强)

#ifndef HEADER_NAME_HPP

#define HEADER_NAME_HPP

             Your Code

#endif //END HEADER_NAME_HPP



(2)   #pragma warning()

#pragma warning( warning-specifier : warning-number-list

[; warning-specifier : warning-number-list...] )

#pragma warning( push[ ,n ] )

#pragma warning( pop )

      

       EG:

       #pragma warning( disable : 4507 34; once : 4385; error : 164 )

等价于:

#pragma warning(disable:4507 34) // 不显示和号警告信息

#pragma warning(once:4385)       // 4385号警告信息仅报告一次

#pragma warning(error:164)       // 把号警告信息作为一个错误。



同时这个pragma warning 也支持如下格式:

#pragma warning( push [ ,n ] )

#pragma warning( pop )

这里n代表一个警告等级(1---4)。

#pragma warning( push )保存所有警告信息的现有的警告状态。

#pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告

等级设定为n。

#pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的

一切改动取消。例如:

#pragma warning( push )

#pragma warning( disable : 4705 )

#pragma warning( disable : 4706 )

#pragma warning( disable : 4707 )

//.......

#pragma warning( pop )

在这段代码的最后,重新保存所有的警告信息(包括,和)。

(3)   #pragma warning()

#pragma warning( warning-specifier : warning-number-list

[; warning-specifier : warning-number-list...] )

#pragma warning( push[ ,n ] )

#pragma warning( pop )

      

       EG:

       #pragma warning( disable : 4507 34; once : 4385; error : 164 )

等价于:

#pragma warning(disable:4507 34) // 不显示和号警告信息

#pragma warning(once:4385)       // 4385号警告信息仅报告一次

#pragma warning(error:164)       // 把号警告信息作为一个错误。



同时这个pragma warning 也支持如下格式:

#pragma warning( push [ ,n ] )

#pragma warning( pop )

这里n代表一个警告等级(1---4)。

#pragma warning( push )保存所有警告信息的现有的警告状态。

#pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告

等级设定为n。

#pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的

一切改动取消。例如:

#pragma warning( push )

#pragma warning( disable : 4705 )

#pragma warning( disable : 4706 )

#pragma warning( disable : 4707 )

//.......

#pragma warning( pop )

在这段代码的最后,重新保存所有的警告信息(包括,和)。

四.        #import

常用于导入.dll



五.        #error

    该指令用于程序的调试, 当编译中遇到#error指令就停止编译。

     #if !defined(__cplusplus)

#error C++ compiler required.

#endif

如果没有在__cplusplus环境下,就会输出This software requires the cplusplus OS.然后诱发编译器终止。所以总的来说,这条指令的目的就是在程序崩溃之前能够给出一定的信息。

六.        #line

用于重置__FILE__和__LINE__

初看起来似乎没有什么用,不过,他还是有点用的,那就是用在编译器的编写中,我们知道编译器对C++源码编译过程中会产生一些中间文件,通过这条指令,可以保证文件名是固定的,不会被这些中间文件代替,有利于进行分析


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ianleelj/archive/2009/02/26/3939607.aspx
分享到:
评论

相关推荐

    C++预编译指令用法

    c++几个预编译指令用法:#undef ,#ifdef,#ifndef,#if

    关于预编译头文件

    预编译头文件说明 C/C++头文件一览 预处理的由来 常见的预处理功能 预处理指令 文件包含指令

    hexrays破解版C++反编译工具.zip

    它能处理任何主流的C/C++编译器产生的代码。浮点指令(也就是XMM/MMX/SSE)是不支援的。它拥有互动和批次处理模式。它是一个IDA Pro插件的载体。IDA 5.1或者更高的版本都是必须的。Hex-Rays Decompiler支持 IntelX86...

    宏和预编译(书中截图笔记)

    由浅入深学c++——基础进阶与做300题

    c++程序using声明和using编译指令.zip

    c++程序using声明和using编译指令.zip

    C/C++程序编译流程详解

    经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。 读取C/C++源程序,对其中的伪指令(以#开头的指令)进行处理 ①将所有的“#...

    C++ 自考模拟试题

    C++ 自考模拟试题 这个是第六套 共有七套

    Boost C++ Libraries 1.63.0,Windows + MinGW 编译

    Boost编译指令:b2.exe --build-type=complete toolset=gcc variant=release link=static threading=multi runtime-link=static install 对于QT使用,已经写好一个 boost.pri 文件放在Boost目录下,只需要在 *.pro ...

    如何在C++中添加头文件,c++万能库头文件

    避免重复包含:为了避免同一个头文件被多次包含,通常会在头文件的开头和结尾使用预处理器指令来防止重复包含 编译程序:最后,使用C++编译器编译你的程序。编译器会处理所有的#include指令,并将包含的头文件内容...

    在C++中使用openmp进行多线程编程

    多线程在实际的编程中的重要性不言而喻。对于C++而言,当我们需要使用多线程时,可以使用boost::thread库或者自从C++ ...在Linux平台上,如果需要使用omp,只需在编译时使用"-fopenmp"指令。在Windows的visual

    花指令添加器2.0

    花指令添加器2.0

    win10+vs2019+bazel+编译tensorflow2.1.1-CPU版(含测试程序)

    Win10下编译的Tensorflow-v2.1.1 C++库 CPU版 win10+vs2019+py3.7.9+bazel0.29.1+tensorflow2.1.1-CPU 支持AVX2指令集 由于机器无N卡,只能编译cpu版,后续再编译其他版本 测试程序含官方的c++例子和网上找的代码,...

    浅谈c++ 预处理器

    预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。 所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号(;)结尾。 我们...

    C++从零开始---入门教程

    C++从零开始(十六)——何谓预编译指令(说明预编译指令的概念及几个常用指令 的应用) C++从零开始(十七)——C++中的一些生僻关键字(explicit、mutable、volatile等的说 明) C++从零开始(十八)——何谓SDK...

    C++编写DLL动态链接库的步骤与实现方法

    本文实例讲述了C++编写DLL动态链接库的步骤与实现方法。分享给大家供大家参考,具体如下: ...为了能让客户端程序和DLL程序公用该类的一份头文件,通常在类的头文件中使用宏和预编译指令来处理。如下DLLTest.h:

    转载:已编译好的openssh库

    四、附录:在VC中对C/C++ 运行时库不同版本编译指令说明 《在VC中对C/C++ 运行时库不同版本编译指令说明》(http://blog.yesky.com/271/dgkang/1737771.shtml)一文中详细介绍了连接不同版本库的编译指令如下: C ...

    ARM C/C++编译器

    ARM C/C++编译器可以被使用... 其中,armcc用于将遵循ANSI C标准的C语言源程序编译成32位的ARM指令代码,它通过了Plum Hall C Validatin Suite测试。armcpp用于将遵循ANSI C++或者EC++标准的C++语言源程序编译成

    ZXing C++编译用的CPPgithub资源和配套的stb资源

    ZXing C++编译用的CPPgithub资源和配套的stb资源 zxing-cpp stb 编译指令 cmake -S zxing-cpp -B zxing-cpp.release -DCMAKE_BUILD_TYPE=Release cmake --build zxing-cpp.release -j8 --config Release

    小熊猫c++开发工具(Dev-C++升级版本)免安装版本

    Dev-C++是一个小巧的开源C/C++ 集成开发环境,解压即可不需要配置环境即可使用,功能强大,有提示又稳定,比vscode、visual studio,非常适合于C/C++ 语言的初学者使用,但是到2015年后已停止开发。 因为教学的需要...

Global site tag (gtag.js) - Google Analytics