49 CPP编译预处理

C++程序编译的过程:预处理->编译(优化、汇编)->链接

预处理与程序员的关系比较大

预处理指令主要有以下三种:

- 包含头文件:#include

- 宏定义:#define (定义宏)、#undef (删除宏)

- 条件编译:#ifdef、#ifndef

1)包含头文件

#include 包含头文件有两种方式:

  • #include :直接从编译器自带的函数库目录中寻找文件。
  • #include "文件名":先从自定义的目录中寻找文件,如果找不到,再从编译器自带的函数库目录中寻找.

#include也包含其它文件,如:*.h、*。cpp或其它 的文件。

C++98标准后的头文件:

  • C的标准库:老版本的有.h后缀;新版本没有.h的后缀,增加了字符c的前缀。例如:老版本是,新版本是,新老版本库中的内容是一样的。在程序中,不指定std命名空间也能使用库中内容。
  • C++的标准库:老版本的有.h后缀;新版本没有.h的后缀。例如:老版本是,新版本是,老版本已弃用,只能用新版本。在程序中,必须指定std命名空间才能使用库中的内容。

注意:用户自定义的头文件还是可以用.h为后缀的

include包含文件的本质是把需要包含的文件的内容复制进来。

2)宏定义指令

无参数的宏:#define 宏名 宏内容

有参数的宏:#define MAX(x,y) ((x)>(y)?(x):(y))

编译的时候,编译器把程序中的宏名用宏内容替换,是为宏展开(宏替换)。

宏可以只有宏名,没有宏内容

在C++中,内联函数可以代替有参数的宏,效果更好。

C++常用的宏:

  • 当前源代码文件名:__FILE__
  • 当前源代码函数名:__FUNCTION__
  • 当前源代码行号:__LINE__
  • 编译的日期:__DATE__
  • 编译的时间:__TIME__
  • 编译的时间戳:__TIMESTAMP__
  • 当用C++编译程序时,宏__cplusplus就会被定义
  • #include <iostream>
    using namespace std;
    
    #define BH 3
    #define MESSAGE "hello world"
    
    void test()
    {
        cout << BH << MESSAGE << endl;
        cout << __FILE__ << endl;
        cout << __FUNCTION__ << endl;
        cout << __LINE__ << endl;
        cout << __DATE__ << endl;
        cout << __TIME__ << endl;
        cout << __TIMESTAMP__ << endl;
        cout << __cplusplus << endl;
    }
    int main()
    {
        test();
        return 0;
    }
    3hello world
    main.cpp
    test
    12
    Nov 23 2022
    21:07:12
    Wed Nov 23 21:07:11 2022
    201103

    3)条件编译

    最常用的两种:#ifdef、#ifndef if #define if not # define

    #ifdef 宏名

    程序段一

    #else

    程序段二

    #endif

    含义:如果#ifdef后面宏名已存在,则使用程序段一,否则使用程序段二。

    #ifndef 宏名

    程序段一

    #else

    程序段二

    #endif

    含义:如果#ifndef后面宏名不存在,则使用程序段一,否则使用程序段二。

  • #include <iostream>
    using namespace std;
    
    void test()
    {
    //不同操作系统的宏:__linux_  _WIN32
    #ifdef _WIN32
        cout << "这是windows系统" << endl;
        typedef long long int64;
    #else
        cout << "这不是windows系统" << endl;
        typedef long int64;
    #endif
        int64 a = 10;
        cout << "a=" << a << endl;
    }
    int main()
    {
        test();
        return 0;
    }
    这是windows系统
    a=10

    条件编译的意思是,如果条件满足,就是用这段代码来编译,如果条件不满足就不用这段代码,不满足就当这段代码不存在,也不会编译它。所以下面这段代码在windows下面是不会报错的,因为另外一个分支的错误代码不会被编译

  • #include <iostream>
    using namespace std;
    
    void test()
    {
    //不同操作系统的宏:__linux_  _WIN32
    #ifdef _WIN32
        cout << "这是windows系统" << endl;
        typedef long long int64;
    #else
        cout << "这不是windows系统" << endl;
        typedef long int64;
        fasdfas
            fasdfasd
                werqwerqw
    #endif
        int64 a = 10;
        cout << "a=" << a << endl;
    }
    int main()
    {
        test();
        return 0;
    }

    if else语句和条件编译不一样,不管什么样的条件,两个分支都会编译。

    4)解决头文件中代码重复包含的问题

    在C/C++中,在使用预编译指令#include的时候,为了防止头文件被重复包含,有两种方式.

    第一种:用#ifdef指令

    #ifndef __PERSON__

    #define __PERSON__

    //代码内容

    #endif

    第二种:把#pagma once 指令放在文件的开头

    #ifndef方式收C/C++语言标准的支持,不受编译器的人和限制;

    而#pragma once方式有些编译器不支持。

    #ifndef可以针对文件中的部分代码;而#pragma once只能针对整个文件。

    #ifndef更加灵活 兼容性也好 #pragma once操作简单 效率高

  • #include <iostream>
    
    #ifndef __PERSON__
    #define __PERSON__
    class Person
    {
    };
    #endif // DEBUG
    using namespace std;
    
    void test()
    {
        Person p;
    }
    int main()
    {
        test();
        return 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值