• (C/C++学习笔记) 十六. 预处理


    十六. 预处理

    ● 关键字typeof

    作用: 为一个已有的数据类型起一个或多个别名(alias), 从而增加了代码的可读性.

    typedef known_type_name new_type_name1, new_type_name2...

    例如:

    typedef double Area, Volume;    //double类型有AreaVolume两个别名

    typedef int integer;

    integer a, b;     //就相当于int a, b;

    #include <iostream.h>

    typedef char * String;    //一般将typeof语句置于声明区, 头文件声明和宏定义之后; 为字符型指针起一个别名, String

     

    void main()

    {

        String str;

        char temp[]="Hello World";

        str=temp;

        cout << str << endl;

    }

     

    typedef后接两个别名

    typedef char *PCHAR,*PSTR;

    //char*取了两个新名字:一个叫PCHAR,另一个叫PSTR

    typedef char *PCHAR,PSTR;

    //char*取个新名字叫PCHAR,给char取新名字叫PSTR

     

     

    ● 预编译=预处理

    预编译=预处理Precompiling=Preprocessing

    预处理包括: ① 宏定义(上文已讲述); ② 文件包含; ③ 条件编译

     

    ● 文件包含

    header file: 头文件, 可能翻译成"标题文件"更好

    如果include包含的头文件在C/C++库函数中,那么就用#include < >, 如果包含的文件在当前目录下,那么用#inlclude " "

    //file1.h

    #define AAA 2

    const int a = 3;

     

    //file2.c

    #include <stdio.h>

    #include "file1.h"

     

    void print_OK(int a)

    {

        printf("OK, %d ", a);

    }

     

    int main(void)

    {

    #if AAA    //如果AAA宏定义的值为真(即非0)

        print_OK(a);

    #endif

        return 0;    //结束一个#if……#else条件编译块

    }

     

    //文件包含命令执行后, file1.c

    #include <stdio.h>

    #define AAA 2

    const int a = 3;

     

    void print_OK(int a)

    {

        printf("OK, %d ", a);

    }

     

    int main(void)

    {

    #if AAA    //如果AAA宏定义的值为真(即非0)

        print_OK(a);

    #endif

        return 0;    //结束一个#if……#else条件编译块

    }

    ● 一般将如下内容放到.h文件中:

    ① 宏定义;

    ② 结构体, 联合体和枚举声明

    typedef声明

    1. 外部函数声明

    ※ 在需要调用函数的文件中,用extern对函数声明,表示该函数是在其他文件中定义的外部函数

    1. 全局变量声明

     

    ● 条件编译(conditional compilation)

    作用: 只对满足一定条件的代码进行编译, 使用条件编译可方便地处理程序的调试版本(Debug Version)和正式(发行)版本(Release Version), 同时增强程序的可移植性.

    #

    空指令,无任何效果

    #include

    包含一个源代码文件

    #define

    定义宏

    #undef

    取消已定义的宏

    #if

    如果给定条件为真,则编译下面代码

    #ifdef

    如果宏已经定义,则编译下面代码

    #ifndef

    如果宏没有定义,则编译下面代码

    #elif

    如果前面的#if给定条件不为真,当前条件为真,则编译下面代码

    #endif

    结束一个#if……#else条件编译块

    #error

    停止编译并显示错误信息

     

    ● ① #if 指令 #if directive, ② #else指令, #elif指令

    #if 指令 #if directive, ② #else指令, #elif指令

    define 标识符 字符串

    ① 简单形式:

    #if constant_expression

        block_statement;

    #endif

    例如:

    #if CPU == Pentium4 //如果是一个整型常数, 0为真, 执行下面的语句, 0为假, 不执行下面的语句

    printf(" Performance should be good." );

    #endif

     

    ② 复杂形式:

    #if condition_1

        statement_block_1;

    #elif condition_2

        statement_block_2;

        ...

    #elif condition_n

        statement_block_n;

    #else

        default_statement_block;

    #endif

    //案例1:

    #include<stdio.h>

    #define NUM 50

     

    main()

    {

        int i=0;

    #if NUM>50                                        /*判断NUM是否大于50*/

        i++;

    #endif

    #if NUM==50

        i=i+50;

    #endif

    #if NUM<50

        i--;

    #endif

        printf("Now i is:%d ",i);

    }

    //案例2:

    #include<stdio.h>

    #define NUM 50

     

    main()

    {

        int i=0;

    #if NUM>50

        i++;

    #else

    #if NUM<50

        i--;

    #else

        i=i+50;

    #endif

    #endif    //第一个#if和最后一个#endif搭配, 第二个#if和倒数第二个if搭配

        printf("i is:%d ",i);

    }

     

    //案例3:

    #include<stdio.h>

    #define NUM 50

    main()

    {

        int i=0;

    #if NUM>50

    i++;        

    #elif NUM<50                            

    i--;     

    #else

    i=i+50;            

    #endif

        printf("i is:%d ",i);

    }

     

    #ifdef指令, #ifndef指令

    //#ifdef的使用:

    #ifdef macro_name

        block_statement_1;

    #endif

    //或者:

    #ifdef macro

        block_statement_1;

    #else

        block_statement_2;

    #endif

        

    //#ifndef的使用:

    #ifndef macro_name

        block_statement_1;

    #endif

    //或者:

    #ifndef macro

        block_statement_1;

    #else

        block_statement_2;

    #endif

    //案例:

    #include<stdio.h>

    #define STR "diligence is the parent of success "

     

    main()

    {

    #ifdef STR

    printf(STR);

    #else

    printf("idleness is the root of all evil ");

    #endif

    printf(" ");

    #ifndef ABC

    printf("idleness is the root of all evil ");

    #else

    printf(STR);

    #endif

    }

     

    #undef指令

    作用: 将宏定义局限在仅需要它的代码中

    #undef macro_name

    #define MAX_SIZE 100

    char array[MAX_SIZE];

    #undef MAX_SIZE

     

    ● 预定义宏(predefined macros) / 预定义标识符(predefined identifiers)

     

    __DATE__: 进行预处理的日期("Mmm dd yyyy"形式的字符串文字)

    __FILE__: 代表当前源代码文件名的字符串文字

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

    __TIME__: 源文件编译时间,格式微"hhmmss"

    __func__: 当前所在函数名(在有的编译器中是: __FUNC____FUNCTION__)

    #include <stdio.h>

    #include <stdlib.h>

    void why_me();

     

    int main()

    {

    printf( "The file is %s. ", __FILE__ );

    printf( "The date is %s. ", __DATE__ );

    printf( "The time is %s. ", __TIME__ );

    printf( "This is line %d. ", __LINE__ );

    //printf( "This function is %s./n", __func__ ); VC++ 6.0不能识别__func__

    why_me();

    return 0;

    }

     

    void why_me()

    {

    //printf( "This function is %s/n", __func__ );

    printf( "The file is %s. ", __FILE__ );

    printf( "This is line %d. ", __LINE__ );

    }

     

    #line指令

    #include "iostream"

    #line 100 "test.cpp"    //如果不指定文件, 就处理当前文件

    using namespace std;    //从这一行开始记作第100

     

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

    {

        cout<<"__LINE__: "<<__LINE__<<endl;

        return 0;

    }

     

    #error指令

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

    //方括号"[]"代表用户自定义的错误消息, 可以省略不写

    /*

    检查编译此源文件的编译器是不是C++编译器

    如果使用的是C语言编译器则执行#error命令

    如果使用的是 C++ 编译器则跳过#error命令

    */

    #ifndef __cplusplus

    #error 亲,您当前使用的不是C++编译器噢!

    #endif

    #include <stdio.h>

    int main()

    {

    printf("Hello,World!");

    return 0;

    }

     

    #pragma指令

    #pragma指令(预处理指令中最复杂的指令)

    作用是设定编译器的状态, 或者提示编译器完成一些特定的动作

    例如: ① 在开发C99时,用C9X代表C99。编译器可以使用下面的编译指示(pragma)来启用对C9X的支持:

    #pragma c9x on

     

    #pragma warning(disable: n)    //作用是将某个警报置为失效

    例如, Visual C++ 2012 使用了更加安全的 run-time library routines, 所以在VS 2012 中编译 C 语言项目,如果使用了 scanf 函数,编译时便会提示如下错误:error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

     

    在声明区写上#pragma warning (disable : 4996)即可忽略编译的错误提示

     

    ● 如何避免头文件被重复包含?

    一般情况下,我们都是把函数声明、类定义、 模板定义等写到一个头文件里, 需要时将相应的头文件用#include 包含到源文件( *.cpp 文件)里来。 但头文件中又允许包含其它的头文件,这样就难免发生某个头文件被重复地包含。 我们可以使用编译预处理命令避免这种情况的发生。

    例如, 你想确保头文件 max.h 不会被重复包含,则你可以采取如下的形式:

    第一条预处理命令是说,如果 MAXMIN_H 不为真,说明此文件没被包含过,此命令后面的源代码有效(相当于:'如果大门没关, 请您进来');

    第二条预处理命令把 MAXMIN_H 置为真(相当于请您把门锁插上,不让第二个人进来)。

    最后一条预处理命令是为了标出接受上述处理的源程序的范围(相当于您已经走到了后门)。

     

     

  • 相关阅读:
    java-this使用
    java-javaBean
    java 构造器
    refs之新旧差异
    angular学习-01引导加载
    mongo 学习02- 基本指令
    mongo 学习01- mongo安装与配置
    node-学习之路04 流式文件
    Vue nodejs商城项目-搭建express框架环境
    Vue nodejs商城项目-项目概述
  • 原文地址:https://www.cnblogs.com/ArrozZhu/p/8377983.html
Copyright © 2020-2023  润新知