c++编译知识

1、 编译介绍

C++语言编译主要分为四个阶段:
源代码:

  #include <stdio.h>
  #include <assert.h>

  #define paster( n ) printf( "token " #n" = %dn ", token##n ) 
  int add(int a, int b);
  int main()
  {
      assert(0);
      int n = 9;
      int token9 = 10;
      paster(9);
      return 0;
  }

1、1 预处理阶段

此阶段主要完成#符号后面的各项内容到源文件的替换,往往一些莫名其妙的错误都是出现在头文件中的,要在工程中注意积累一些错误知识, 此阶段产生[.i]文件。

  • #ifdef等内容,完成条件编译内容的替换
  • #include中内容,在当前目录或者指定目录,或者默认目录搜索头文件,并将头文件拷贝到源文件中。
  • #define的内容,替换define的内容(包括上一步的头文件中的define内容)

注:

  • ##是一个连接符号,用于把参数连在一起
  • #是“字符串化”的意思。出现在宏定义中的#是把跟在后面的参数转换成一个字符串
    示例:
#define paster( n ) printf( "token " #n" = %dn ", token##n ) 

所以paster(9);就是相当于 printf("token 9 = %dn",token9);
注: :-E 为预编译 选项

g++ -E test.cpp -o test.i

查看预编译后的文件:

976 # 3 "test.cpp" 2
977 
978 
979 int add(int a, int b);
980 int main()
981 {
982     ((0) ? static_cast<void> (0) : __assert_fail ("0", "test.cpp", 8, __PRETTY_FUNCTION__));
983     int n = 9;
984     int token9 = 10;
985     printf( "token " "9"" = %dn ", token9 );
986     return 0;
987 }

1、2 编译阶段

此阶段完成语法和语义分析,然后生成中间代码,此中间代码是汇编代码,但是还不可执行,gcc编译的中间文件是[.s]文件。

在此阶段会出现各种语法和语义错误,特别要小心未定义的行为,这往往是致命的错误。

第一个阶段和第二个阶段由编译器完成。
使用:注: -S 为编译选项
命令如下:

 g++ -S test.i  -o test.s

也可以直接生成 .s文件,命令如下:

g++ -S test.cpp -o test.s

查看生成的test.s 文件

        .file   "test.cpp"
        .section        .rodata
.LC0:
        .string "test.cpp"
.LC1:
        .string "0"
        .text
        .file   "test.cpp"
        .section        .rodata
        .file   "test.cpp"
        .section        .rodata
.LC0:
        .string "test.cpp"
.LC1:
        .string "0"
        .text
.globl main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        .cfi_personality 0x3,__gxx_personality_v0
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $_ZZ4mainE19__PRETTY_FUNCTION__, %ecx
        movl    $8, %edx
        movl    $.LC0, %esi
        movl    $.LC1, %edi
        call    __assert_fail
        .cfi_endproc
.LFE0:
        .size   main, .-main

1、3 汇编阶段

此阶段主要完成将汇编代码翻译成机器码指令,并将这些指令打包形成可重定位的目标文件,[.O]文件,是二进制文件。
c
此阶段由汇编器完成。
命令如下:注: -c 为汇编 选项

 g++ -c test.s -o test.o

g++ -c test.cpp -o test.o

1、4 链接阶段

此阶段完成文件中调用的各种函数跟静态库和动态库的连接,并将它们一起打包合并形成目标文件,即可执行文件。

此阶段由链接器完成。
命令如下:注: -c 为链接 选项

 g++ -o test test.cpp 

 g++ test.cpp -o test

或   

 g++ -o test test.o

使用nm -c test 可以查看可执行文件包含的函数;
linux nm和ldd解读

编译图解对应
编译图解对应

原文链接: https://www.cnblogs.com/lihaihui1991/p/14252569.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    c++编译知识

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/400359

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月14日 下午2:06
下一篇 2023年4月14日 下午2:06

相关推荐