跳转至

项目编译流程

约 492 个字 11 行代码 预计阅读时间 2 分钟

单个文件

a.c(a.cpp)

–预处理→ a.i gcc -E a.c -o a.i

– 编译 → a.s gcc -S a.i -o a.s

– 汇编 → a.o gcc -c a.s -o a.o

– 链接 → a.exe gcc a.o -o a.exe

  • 没有 -E/-S/-c:一直做到链接,生成可执行文件

  • -E:做到预处理就停

  • -S:做到编译(生成汇编)就停

  • -c:做到汇编(生成 .o)就停

gcc从输入文件的扩展名中自动获得输入文件是哪一步的结果,并按照预处理-编译-汇编-链接的顺序往下执行, 选项只限制执行到哪一步停止.

多文件编译

.h(有时也是.hpp), .cpp(有时也是.cc)

.h和.cpp文件

  • .h文件只包含函数/全局变量/类声明, 不能包含定义或using namespace.
  • .h文件在预处理阶段被预处理器拷贝进对应的.c里

多文件全局变量声明与定义

  • 声明全局变量使用extern
    //a.h
    extern int N;//声明
    
    //a.cpp
    int N;//定义
    
    //main.cpp
    ......
    int main(){
        N++;
    }
    ......
    
    原理: 首先每个.cpp文件是单独编译的, 在链接之前, 编译器会将使用到变量N的地方作为”对外部符号N的引用”写进.o文件, 而后在链接阶段, 链接器会从所有.o文件中收集外部定义和外部引用, 然后为每个符号匹配定义与引用. 此时链接器会从a.o中收集到int N的定义, 从main.o中收集到int N的引用, 然后建立链接.

如果找不到链接, 会报链接错误: undefined reference to 'N'; 如果找到多个全局int N定义, 也会报链接错误 multiple definition of N

预处理宏

  • 控制头文件被单个cpp文件只引用一次 #pragma once, 但对一些很老版本的编译器不行
  • 条件编译ifndef...#define...#endif, 兼容性较好

多文件函数声明与定义

  • extern "C"用来声明C语言的函数
    extern "C" int func (...); 
    extern "C" int func (...){
    
    }
    

也可以:

extern "C"{
    void func1();
    void func2();
}
extern "C"{
    void func1(){

    }
    void func2(){

    }
}
若调用C语言的库, 也可将C语言头文件include在extern “C”中
extern "C"{
    #include "xxx.h" //需要是.c对应的头文件!
}

c++的函数签名和c的函数签规则是不同的, 所以需要用不同的编译器

多文件对象的声明和定义

评论