zoukankan      html  css  js  c++  java
  • LinuxC++开发记录(g++)

    g++使用

    1. 编译过程

    • 预处理(-E)
    • 编译(-S)
    • 汇编(-c)
    • 链接

    1.1 预处理(-E)

    为了直观的了解预处理,理解预处理做了哪些工作,不说那么多,直接上代码,创建main.h与main.cpp文件,有头文件引用,有宏定义,有注释,还有未定义参数赋值的错误。代码如下:

    /* main.h */
    #define VALUES 100
    int test();
    
    void test2(){}
    
    void test3(){}
    
    void test4(){}
    /* main.cpp */
    #include <main.h>
    
    int main()
    {
        // 参数未定义
        a = 100;
        return test();
    }
    
    int test()
    {
        return VALUES;
    }

    预处理:

    g++ -E main.cpp -I. > main.i
    -I.表示头文件在当前路径

    main.i为:

    # 1 "main.cpp"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 1 "<command-line>" 2
    # 1 "main.cpp"
    # 1 "./main.h" 1
    
    int test();
    
    void test2(){}
    
    void test3(){}
    
    void test4(){}
    # 2 "main.cpp" 2
    
    int main()
    {
    
        a = 100;
        return test();
    }
    
    int test()
    {
        return 100;
    }

    生成很顺利,可以看出,预处理工作:

    1. 不关注语法错误
    2. 宏替换
    3. 消除注释
    4. 将头文件整个包括进来,连空行都是完整的复制过来的

    1.2 编译(-S)

    编译将会把预处理生成的.i文件生成为.s的汇编代码文件。
    继续上面的代码,当我们尝试编译上面生成的main.i文件时,会提示语法错误:

    g++ -S main.i
    main.cpp: In function ‘int main()’:
    main.cpp:6:5: error: ‘a’ was not declared in this scope
         a = 100;

    我们在main.c中加入int a;

    g++ -E main.cpp -I. > main.i
    g++ -S main.i

    这样就可以通过编译,默认生成main.s汇编文件,打开如下:

        .file    "main.cpp"
        .text
        .globl    _Z5test2v
        .type    _Z5test2v, @function
    _Z5test2v:
    .LFB0:
        .cfi_startproc
        pushq    %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        nop
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size    _Z5test2v, .-_Z5test2v
        .globl    _Z5test3v
        .type    _Z5test3v, @function
    _Z5test3v:
    .LFB1:
        .cfi_startproc
        pushq    %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        nop
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE1:
        .size    _Z5test3v, .-_Z5test3v
        .globl    _Z5test4v
        .type    _Z5test4v, @function
    _Z5test4v:
    .LFB2:
        .cfi_startproc
        pushq    %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        nop
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE2:
        .size    _Z5test4v, .-_Z5test4v
        .globl    main
        .type    main, @function
    main:
    .LFB3:
        .cfi_startproc
        pushq    %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $100, -4(%rbp)
        call    _Z4testv
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE3:
        .size    main, .-main
        .globl    _Z4testv
        .type    _Z4testv, @function
    _Z4testv:
    .LFB4:
        .cfi_startproc
        pushq    %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $100, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE4:
        .size    _Z4testv, .-_Z4testv
        .ident    "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609"
        .section    .note.GNU-stack,"",@progbits

    从这开始就和汇编是一样的了,再深入就需要去了解汇编的原理,后面两个过程不再详细描述。

    1.3 汇编(-c)

    汇编的工作是将汇编代码转成机器代码,注意“-c”是小写字母,而预处理和编译都是大写字母。汇编后生成.o目标文件。

    g++ -c main.i

    生成main.o

    1.4 链接(-o)

    将.o、.a、.so等文件链接生成可执行文件。

    g++ main.o -o main

    生成main可执行文件

    g++ main.o

    生成默认的a.out可执行文件

    2. 编译单文件

    g++ main.cpp [-o target_file_name]

    生成单个文件很简单,可通过-o参数指定生成文件名称。不指定则默认生成a.out文件。

    3. 编译同目录下多个文件

    ├── proj
    │   ├── main.cpp
    │   ├── test.cpp
    │   ├── test.h
    g++ main.cpp test.cpp -o main.out

    4. 编译不同目录下多个文件(一次性、参数-I)

    还是上面的代码,目录结构改了,将test.cpp、test.h放到test文件夹下:

    ├── proj
    │   ├── main.cpp
    │   ├── test
    │   │   ├── test.cpp
    │   │   ├── test.h
    g++ main.cpp ./test/test.cpp -Itest -o main.out

    因为test.cpp、test.h和main.cpp不在相同文件夹内,所以需要指定cpp文件地址及.h文件所在目录。
    -I :指定头文件所在目录。

    5. 编译不同目录下多个文件(分步)

    文件结构与4一致。
    4需要指定具体的文件,而且每次编译的时候需要把所有的cpp文件都编译一次,有时候我们只改一个文件并不需要全部重新编译。我们可以将源文件编译成一个.o汇编代码文件,最后再链接再链接在一起。

    目录结构:

    ├── proj
    │   ├── main.cpp
    │   ├── test
    │   │   ├── test.cpp
    │   │   ├── test.h
    │   ├── obj

    生成test.o到obj目录:

    g++ -c ./test/test.cpp -Itest -o ./obj/test.o

    生成可执行文件:

    g++ main.cpp ./obj/test.o -o main.out

    6. g++常用命令选项

  • 相关阅读:
    TypeScript——04——ts中的接口(Interface)
    TypeScript——02——TS基本数据类型介绍和使用
    TypeScript——01——简介以及安装使用
    事件循环 EventLoop(Promise,setTimeOut,async/await执行顺序)
    【vue】vue生命周期---精简易懂-----【XUEBIG】
    【Vue】-- 数据双向绑定的原理 --Object.defineProperty()
    【nodejs】--express的中间件multer实现图片文件上传--【XUEBIG】
    【H5】-- FormData用法介绍以及实现图片/文件上传--【XUEBIG】
    CommonJs规范详解---【XUEBIG】
    从输入 URL 到页面加载完成的过程详解---【XUEBIG】
  • 原文地址:https://www.cnblogs.com/liuzhenbo/p/11031855.html
Copyright © 2011-2022 走看看