zoukankan      html  css  js  c++  java
  • 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++源码编译过程中会产生一些中间文件,通过这条指令,可以保证文件名是固定的,不会被这些中间文件代替,有利于进行分析

    七.        #ifdef  #ifndef  #if  #else  #elif  #endif 条件编译

    预处理器不能识别标记代码块的花括号{},对于条件编译的没有条件判断块必须使用 #endif来指定终止

    1、 
        #ifdef  identifier 
                  your code 
          #endif 
          如果identifier为一个定义了的符号,your code就会被编译,否则剔除 
        2、 
          #ifndef identifier 
                  your code 
          #endif 
          如果identifier为一个未定义的符号,your code就会被编译,否则剔除 
        3、 
          #if  expression 
               your code 
          #endif 
          如果expression非零,your code就会被编译,否则剔除 
        4、 
          #ifdef identifier 
                 your code1 
          #else 
                 your code2 
          #endif 
          如果identifier为一个定义了的符号,your code1就会被编译,否则your code2     

    就会被编译 
        5、 
          #if   expressin1 
                your code1 
          #elif expression2 
                your code2 
          #else 
                your code3 
          #enif   

    八.        预定义宏

        __DATE__       进行预处理的日期

        __FILE__       当前软代码文件名的字符串文字

        __LINE__       当前源代码中的行号的整数常量

        __TIME__       源文件的编译时间

        __TIMESTAMP__  源文件的编译完整时间

    cout << "__DATE__ = " << __DATE__ << endl;

        cout << "__FILE__ = " << __FILE__ << endl;

        cout << "__LINE__ = " << __LINE__ << endl;

        cout << "__TIME__ = " << __TIME__ << endl;

    cout << "__TIMESTAMP__ = " << __TIMESTAMP__ << endl;

  • 相关阅读:
    CentOS安装配置
    扩展多线程应用程序 CLR 和 线程
    OEA体验 :元数据编写
    字符串的逆序之旅
    学习之响应式Web设计:Media Queries和Viewports
    Windows Azure Virtual Machine Role (4) 在VHD中安装需要的功能
    java开发web service快速入门(视频)
    淘宝技术发展(Java时代:脱胎换骨)
    Contoso 大学 使用 EF Code First 创建 MVC 应用
    负载均衡原理与实践详解 第三篇 服务器负载均衡的基本概念网络基础
  • 原文地址:https://www.cnblogs.com/minggoddess/p/1918075.html
Copyright © 2011-2022 走看看