c编译和预处理

作者: 霡霂976447044 | 来源:发表于2019-02-26 14:12 被阅读1次

    编译预处理

    编译预处理处于C程序编译第一步骤,基本操作就是提前处理C中以 # 开头的语句,将源代码里一些代码替换新的代码

    主要分为:

      1. 宏定义,一般格式:#define name value
        1. 变量式宏定义
        1. 函数式宏定义
      1. 文件包含
        #include <filename>
        #include "filename"
      1. 条件编译
      1. assert宏

    宏定义

    源码如下:

    #include<stdio.h>
    #define NAME "zhangsan"
    int main() {
        printf(NAME);
        return 0;
    }
    

    用gcc -E命令可以得到预编译后的代码,如下:

    ...省略
    extern FILE *popen (const char *__command, const char *__modes) ;
    extern int pclose (FILE *__stream);
    extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
    # 914 "/usr/include/stdio.h" 3 4
    extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
    extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
    extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
    # 944 "/usr/include/stdio.h" 3 4
    # 2 "example.c" 2
    # 3 "example.c"
    int main() {
     printf("zhangsan");
     return 0;
    }
    

    注意倒数第三行.NAME替换成为了 “zhangsan”
    那么是因为我们写的源码:

    #define NAME "zhangsan"
    

    这个""双引号是自己写的还是预编译自己加的呢?更改为

    #define NAME zhangsan
    

    重复之前的gcc -E操作,得到

    # 3 "example.c"
    int main() {
     printf(zhangsan);
     return 0;
    }
    

    所以,以宏定义的预编译只是单纯的替换文本的操作。
    注意:在”NAME” 引号包括起来则不会替换。
    可以将宏定义的value定义为表达式巧妙的运算。

    变量式宏定义

    一般形式: #define 标识符 字符串

    #include <stdio.h>
    #define PI 2.1415926
    #define C (2 * PI * radius)
    int main() {
        int radius;
        float circlue;
        printf("Please enter the circle ridius: ");
        scanf("%d",&radius);
        circlue = C;//使用宏定义
        printf("Circle circlue: %f\n",circlue);
        return 0;
    }
    

    gcc -E a.e,tail a.e 查看

    # 4 "define_variable.c"
    int main() {
     int radius;
     float circlue;
     printf("Please enter the circle ridius: ");
     scanf("%d",&radius);
     circlue = (2 * 2.1415926 * radius);
     printf("Circle circlue: %f\n",circlue);
     return 0;
    }
    

    可以看到C被替换了。

    函数式宏定义

    一般形式: #define 标识符(参数列表) 字符串
    把之前的C宏定义改一下:

    #include <stdio.h>
    #define PI 2.1415926
    #define C(r) 2 * PI * r
    int main() {
        int radius;
        float circlue;
        printf("Please enter the circle ridius: ");
        scanf("%d",&radius);
        circlue = C(radius);
        printf("Circle circlue: %f\n",circlue);
        return 0;
    }
    

    注意函数式宏定义宏名字后没有空格
    gcc -E 得到预编译后的代码,tail查看后几行。

    # 4 "define_variable.c"
    int main() {
     int radius;
     float circlue;
     printf("Please enter the circle ridius: ");
     scanf("%d",&radius);
     circlue = 2 * 2.1415926 * radius;
     printf("Circle circlue: %f\n",circlue);
     return 0;
    }
    

    嵌套宏定义

    #include <stdio.h>
    #define A 1
    #define B 2
    #define ADD A+B 
    #define C(r) 2 * PI * r
    int main() {
        int i = ADD;
        printf(" %d\n",i);
        return 0;
    }
    

    多行宏定义

    以\换行

    #include <stdio.h>
    #define exchange(a,b){\
        a = b-a;\
        b = b-a;\
        a = b+a;\
    }
    int main() {
        int i;
        int j;
        printf("Please enter first num:");
        scanf("%d",&i);
        printf("Please enter second num:");
        scanf("%d",&j);
        exchange(i,j);
        printf("Exchanged,First num: %d, second: %d\n",i,j);
        return 0;
    }
    

    文件包含

    文件包含也是替换操作。
    Test.h

    #define DATA "Hello!"
    void showData();
    

    Test.c

    #include "Test.h"
    #include <stdio.h>
    void showData() {
        printf(DATA);
    }
    

    Main.c

    #include <stdio.h>
    #include "Test.h"
    int main() {
        printf("调用Test.h的showData方法:\n");
        showData();
        return 0;
    }
    

    根据以上几个文件得到预编译文件Main.i

    ......
    extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
    # 944 "/usr/include/stdio.h" 3 4
    # 2 "Main.c" 2
    # 1 "Test.h" 1
    # 2 "Test.h"
    void showData();
    # 3 "Main.c" 2
    int main() {
     printf("调用Test.h的showData方法:\n");
     showData();
     return 0;
    }
    

    嵌套包含和条件编译

    一般在头文件里定义的时候

    #ifndef _TEST_H
    #define _TEST_H
    #define DATA "Hello!"
    void showData();
    #endif
    

    相关文章

      网友评论

        本文标题:c编译和预处理

        本文链接:https://www.haomeiwen.com/subject/oseayqtx.html