zoukankan      html  css  js  c++  java
  • C Primer Plus--C预处理器和C库(2)

    #include指令

    • #include <头文件.h>//在标准系统目录中寻找头文件
    • #include "头文件.h"//先在当前目录下面寻找头文件,然后在标准系统目录下寻找头文件

    预处理器在碰到#inclide指令时,就会将后面附加的头文件的内容包含到当前文件中。

    头文件

    后缀为.h的文件是头文件。这类文件经常包含预处理器所需要的语句。
    头文件内容最常见形式包括:

    • 明显常量
    • 宏函数
    • 函数声明
    • 结构模板定义
    • 类型定义

    其他指令

    #undef

    #undef指令取消一个给定的已定义#define.

    #define FF 10
    
    #undef FF //FF定义被取消
    

    条件编译

    #ifdef #else #endif

    #ifdef后面的标识符如果已经定义了,那么执行它的分支控制的指令,知道下一个#else#endif为止。如果有#else存在,那么在未定义时会执行#else知道#endif之间的所有指令。

    #define FF 10
    
    #ifdef FF
    #define AA 100
    #else
    #define AA 1000
    #endif
    
    int main() {
        printf("FF :%d
    ",AA);
    }
    

    #ifndef

    #ifndef#ifdef的反义词,它是用来确定后面的表示符未被定义。通常用来定义此前未被定义的常量。

    #ifndef FF
    #define FF 199
    #endif
    int main() {
        printf("FF :%d
    ",FF);
    }
    

    #ifndef也可以用于防止多次包含同一文件。

    /*
     *假设这个头文件是test.h
     */
     //原本头文件的内容直接写,现在我们把头文件的内容放到下面这样的结构里:
     #ifndef _TEST_H
     #define _TEST_H
     /*
      *#define和#endif之间存放头文件的所有内容
      */
     #endif
    

    来看看上面这段代码什么意思:
    首先,明确我们的目的:防止一个文件被多次的include。为什么会存在多次include呢?因为可能一个文件会include多个文件,而不同文件有可能include同一个文件,而在一个文件中只能对一个文件中include一次。举个栗子:存在a.h,b.h,test.h,有可能a.h中有一个#include "test.h",同时b.c中有两行

    #include "a.h"
    #include "test.h"
    

    这样就出现了b.h被包含了两次,而C是不允许这样的。上面用到#ifndef就解决了这个问题。
    test.h未被定义,也就是说这个头文件被第一次包含了,会定义一个_TEST_H的常量,但没有body,因为我们不需要这个常量具有body。这时候头文件里的所有内容被预处理器执行。当test.h被第二次包含时,预处理器检测到已经存在_TEST_H这个量,就会跳过,也就不会重复执行头文件里的内容了。这里的关键是保持_TEST_H的唯一。我们这里用头文件的文件名做标识符,将文件名前面加下划线,并将点换成下划线,能够保证这个标识符不重复。但这种做法是编译器提供商为了标准头文件采用的方法,我们平时自己写的时候要想防止与标准头文件冲突,就不要按这种方法来取标识符。例如可以把下划线加到文件名后面等等。

    #if#elif

    #if#elif后面跟常量整数表达式,当这个表达式值为非0值时为真,为0位假,类似于C程序中的if-else分支结构。可以应用C的关系运算符以及逻辑运算符。

    #if defined(FF)
    #define SS 9999
    #elif defined(_TEST_H)
    #define EE 99
    #endif
    

    预定义宏

    一些常见的预定义宏:

    意义
    __DATE__ 进行预处理操作的日期字符串
    __FILE__ 当前源代码文件名的字符串
    __LINE__ 当前所在代买行号
    __TIME__ 源文件编译时间
    __STDC_VERSION__ 当前编译器遵循的C标准版本,当为C99时值为199901L

    #line#error

    #line指令用于重置由__LINE____FILE__宏报告的行号和文件名。
    使用方法:

    #line 100 //当前行号重置为100
    #line 10 "test.c" //把行号重置为10,文件名重置为test.c
    
    printf("%d
    ",__LINE__);
    #line 1000
    printf("%d
    ",__LINE__);
    printf("%d
    ",__LINE__);
    

    #error指令使预处理器发出一条错误消息,该消息包含指令中的文本。可能的话,编译过程应该中断。

    #if __STDC_VERSION__ != 199901L
    #error Not C99
    #endif
    

    内联函数

    内联函数主要是为了把解决函数调用过程中建立调用、传递参数、跳转到函数代码段返回耗费的时间较长的问题。它适用于较短代码块,创建内联函数需要用到inline关键字。

    inline double square(double x);
    double square(double x){
        return x*x;
    }
    int main() {
        double a = square(3);
        printf("%lf
    ",a);
    }
    //内联函数这里其实把函数体直接写到了main里面,不用调用了。
    /*
     *int main(){
     *	double a = a * a;
     *	printf("%lf
    ",a);
     *}
     */
    

    无法获取内联函数的地址,因为内联函数并没有被分配单独的空间。内联函数适用于短小函数,长的函数调用造成的时间远远小于函数体执行时间,使用内联函数并没什么意义。
    内联函数的定义和对该函数的调用必须在同一文件中。因此,内联函数一般具有内部链接。在多文件程序中,要想使用相同的内联函数,必须在每个文件中对内联函数进行定义。为了方便,可以把内联函数的定义放在头文件中。

    世事茫茫,光阴何其有限!
  • 相关阅读:
    oracle取字符串长度的函数length()和hengthb()
    文件操作
    numpy 库使用
    numpy 与 matplotlib 的应用过程
    使用numpy与matplotlib.pyplot画图
    面向对象的解读
    Python PIL
    Note of Jieba
    python 游戏 —— 汉诺塔(Hanoita)
    有进度条圆周率Π计算
  • 原文地址:https://www.cnblogs.com/bobliao/p/9946522.html
Copyright © 2011-2022 走看看