c语言中源文件编译后生成的文件是什么

发布时间:2022-11-24 09:49:11 作者:iii
来源:亿速云 阅读:420

C语言中源文件编译后生成的文件是什么

引言

在C语言编程中,源代码文件(通常以.c为扩展名)需要经过编译器的处理才能生成可执行文件。编译过程涉及多个步骤,每个步骤都会生成不同类型的中间文件。本文将详细探讨C语言源文件编译后生成的文件类型及其作用,帮助读者深入理解C语言编译过程。

1. 编译过程概述

C语言的编译过程通常分为以下几个阶段:

  1. 预处理(Preprocessing)
  2. 编译(Compilation)
  3. 汇编(Assembly)
  4. 链接(Linking)

每个阶段都会生成相应的中间文件,最终生成可执行文件。下面我们将逐一介绍每个阶段生成的文件。

2. 预处理阶段

2.1 预处理器的功能

预处理器是编译过程的第一步,主要负责处理源代码中的预处理指令。常见的预处理指令包括#include#define#ifdef等。预处理器会根据这些指令对源代码进行修改,生成一个经过预处理的源代码文件。

2.2 预处理后生成的文件

在预处理阶段,编译器会生成一个扩展名为.i的文件。这个文件包含了经过预处理的源代码,所有的宏定义已经被展开,所有的#include指令已经被替换为相应的头文件内容。

例如,假设我们有一个名为main.c的源文件,经过预处理后会生成一个main.i文件。

gcc -E main.c -o main.i

2.3 预处理文件的内容

main.i文件的内容通常比原始源文件大得多,因为它包含了所有被包含的头文件内容。例如:

# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 392 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 393 "/usr/include/features.h" 2 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 3 4
# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/gnu/stubs.h" 2 3 4
# 394 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4
...

3. 编译阶段

3.1 编译器的功能

在编译阶段,编译器将预处理后的源代码(.i文件)转换为汇编代码。汇编代码是一种低级语言,与机器指令一一对应,但仍然是人类可读的。

3.2 编译后生成的文件

在编译阶段,编译器会生成一个扩展名为.s的文件。这个文件包含了与源代码对应的汇编代码。

例如,继续以main.c为例,经过编译后会生成一个main.s文件。

gcc -S main.i -o main.s

3.3 汇编文件的内容

main.s文件的内容是汇编代码,通常如下所示:

    .file   "main.c"
    .section    .rodata
.LC0:
    .string "Hello, World!"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    leaq    .LC0(%rip), %rdi
    call    puts@PLT
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
    .section    .note.GNU-stack,"",@progbits

4. 汇编阶段

4.1 汇编器的功能

在汇编阶段,汇编器将汇编代码(.s文件)转换为机器代码,生成目标文件。目标文件包含了机器指令,但尚未进行链接,因此还不能直接执行。

4.2 汇编后生成的文件

在汇编阶段,编译器会生成一个扩展名为.o的文件。这个文件是目标文件,包含了机器代码和符号表等信息。

例如,继续以main.c为例,经过汇编后会生成一个main.o文件。

gcc -c main.s -o main.o

4.3 目标文件的内容

目标文件(.o文件)是二进制文件,通常不可直接阅读。它包含了机器指令、符号表、重定位信息等。目标文件的内容可以通过工具如objdumpnm来查看。

objdump -d main.o

输出示例:

main.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # b <main+0xb>
   b:   e8 00 00 00 00          callq  10 <main+0x10>
  10:   b8 00 00 00 00          mov    $0x0,%eax
  15:   5d                      pop    %rbp
  16:   c3                      retq

5. 链接阶段

5.1 链接器的功能

在链接阶段,链接器将一个或多个目标文件(.o文件)以及库文件(如标准库)合并,生成最终的可执行文件。链接器的主要任务是解析符号引用,将各个目标文件中的代码和数据段合并,并生成可执行文件。

5.2 链接后生成的文件

在链接阶段,编译器会生成一个可执行文件。在Linux系统中,可执行文件通常没有扩展名,而在Windows系统中,可执行文件的扩展名为.exe

例如,继续以main.c为例,经过链接后会生成一个名为main的可执行文件。

gcc main.o -o main

5.3 可执行文件的内容

可执行文件是二进制文件,包含了机器指令、数据段、符号表、重定位信息等。可执行文件的内容可以通过工具如objdumpreadelf来查看。

objdump -d main

输出示例:

main:     file format elf64-x86-64

Disassembly of section .init:

0000000000401000 <_init>:
  401000:       48 83 ec 08             sub    $0x8,%rsp
  401004:       48 8b 05 ed 2f 00 00    mov    0x2fed(%rip),%rax        # 403ff8 <__gmon_start__>
  40100b:       48 85 c0                test   %rax,%rax
  40100e:       74 02                   je     401012 <_init+0x12>
  401010:       ff d0                   callq  *%rax
  401012:       48 83 c4 08             add    $0x8,%rsp
  401016:       c3                      retq

Disassembly of section .plt:

0000000000401020 <.plt>:
  401020:       ff 35 e2 2f 00 00       pushq  0x2fe2(%rip)        # 404008 <_GLOBAL_OFFSET_TABLE_+0x8>
  401026:       ff 25 e4 2f 00 00       jmpq   *0x2fe4(%rip)        # 404010 <_GLOBAL_OFFSET_TABLE_+0x10>
  40102c:       0f 1f 40 00             nopl   0x0(%rax)

0000000000401030 <puts@plt>:
  401030:       ff 25 e2 2f 00 00       jmpq   *0x2fe2(%rip)        # 404018 <puts@GLIBC_2.2.5>
  401036:       68 00 00 00 00          pushq  $0x0
  40103b:       e9 e0 ff ff ff          jmpq   401020 <.plt>

Disassembly of section .text:

0000000000401040 <_start>:
  401040:       31 ed                   xor    %ebp,%ebp
  401042:       49 89 d1                mov    %rdx,%r9
  401045:       5e                      pop    %rsi
  401046:       48 89 e2                mov    %rsp,%rdx
  401049:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
  40104d:       50                      push   %rax
  40104e:       54                      push   %rsp
  40104f:       49 c7 c0 00 11 40 00    mov    $0x401100,%r8
  401056:       48 c7 c1 90 10 40 00    mov    $0x401090,%rcx
  40105d:       48 c7 c7 36 11 40 00    mov    $0x401136,%rdi
  401064:       ff 15 86 2f 00 00       callq  *0x2f86(%rip)        # 403ff0 <__libc_start_main@GLIBC_2.2.5>
  40106a:       f4                      hlt
  40106b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

0000000000401070 <deregister_tm_clones>:
  401070:       b8 30 40 40 00          mov    $0x404030,%eax
  401075:       48 3d 30 40 40 00       cmp    $0x404030,%rax
  40107b:       74 13                   je     401090 <deregister_tm_clones+0x20>
  40107d:       b8 00 00 00 00          mov    $0x0,%eax
  401082:       48 85 c0                test   %rax,%rax
  401085:       74 09                   je     401090 <deregister_tm_clones+0x20>
  401087:       ff e0                   jmpq   *%rax
  401089:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  401090:       c3                      retq
  401091:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  401098:       00 00 00
  40109b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

00000000004010a0 <register_tm_clones>:
  4010a0:       be 30 40 40 00          mov    $0x404030,%esi
  4010a5:       48 81 ee 30 40 40 00    sub    $0x404030,%rsi
  4010ac:       48 c1 fe 03             sar    $0x3,%rsi
  4010b0:       48 89 f0                mov    %rsi,%rax
  4010b3:       48 c1 e8 3f             shr    $0x3f,%rax
  4010b7:       48 01 c6                add    %rax,%rsi
  4010ba:       48 d1 fe                sar    %rsi
  4010bc:       74 11                   je     4010cf <register_tm_clones+0x2f>
  4010be:       b8 00 00 00 00          mov    $0x0,%eax
  4010c3:       48 85 c0                test   %rax,%rax
  4010c6:       74 07                   je     4010cf <register_tm_clones+0x2f>
  4010c8:       ff e0                   jmpq   *%rax
  4010ca:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  4010d0:       c3                      retq
  4010d1:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)
  4010d8:       00 00 00 00
  4010dc:       0f 1f 40 00             nopl   0x0(%rax)

00000000004010e0 <__do_global_dtors_aux>:
  4010e0:       80 3d 49 2f 00 00 00    cmpb   $0x0,0x2f49(%rip)        # 404030 <__TMC_END__>
  4010e7:       75 17                   jne    401100 <__do_global_dtors_aux+0x20>
  4010e9:       55                      push   %rbp
  4010ea:       48 89 e5                mov    %rsp,%rbp
  4010ed:       e8 7e ff ff ff          callq  401070 <deregister_tm_clones>
  4010f2:       c6 05 37 2f 00 00 01    movb   $0x1,0x2f37(%rip)        # 404030 <__TMC_END__>
  4010f9:       5d                      pop    %rbp
  4010fa:       c3                      retq
  4010fb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  401100:       f3 c3                   repz retq
  401102:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  401109:       00 00 00
  40110c:       0f 1f 40 00             nopl   0x0(%rax)

0000000000401110 <frame_dummy>:
  401110:       eb 8e                   jmp    4010a0 <register_tm_clones>
  401112:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  401119:       00 00 00
  40111c:       0f 1f 40 00             nopl   0x0(%rax)

0000000000401120 <main>:
  401120:       55                      push   %rbp
  401121:       48 89 e5                mov    %rsp,%rbp
  401124:       48 8d 3d d9 0e 00 00    lea    0xed9(%rip),%rdi        # 402004 <_IO_stdin_used+0x4>
  40112b:       e8 00 00 00 00          callq  401130 <main+0x10>
  401130:       b8 00 00 00 00          mov    $0x0,%eax
  401135:       5d                      pop    %rbp
  401136:       c3                      retq
  401137:       66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  40113e:       00 00

6. 总结

C语言源文件编译后生成的文件类型包括:

  1. 预处理文件(.i文件):经过预处理的源代码文件。
  2. 汇编文件(.s文件):与源代码对应的汇编代码文件。
  3. 目标文件(.o文件):包含机器代码和符号表的目标文件。
  4. 可执行文件:最终生成的可执行文件,可以直接运行。

理解这些文件的生成过程及其内容,有助于深入理解C语言的编译过程,并在调试和优化代码时提供帮助。

推荐阅读:
  1. python源文件的后缀是什么?
  2. c程序编译后生成什么文件?后缀是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c语言

上一篇:go语言中goto如何用

下一篇:php怎么修改时区

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》