C语言源代码一般保存为什么扩展名,c语言为什么需要编译链接

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

c语言为什么需要编译链接

朱有鹏

1、C语言为什么需要编译链接

1.1、编译链接的流程

(1)编译流程图

51c2f9c219050cb64bd57ea6ce590bdb.png

(2)编译链接实例

由源码到可执行程序的整个过程:以我们再熟悉不过的hello.c为例

Hello.c

#include

int main(int argc, char *argv[])

{

printf("hello world.\n");

return 0;

}

对于这个c语言程序,我们必须经过一定手段,将其编程二进制可执行文件,然后由系统加载执行。在Linux系统中,gcc编译时,gcc编译程序会读取源代码hello.c文件,并且将其翻译成一个可执行文件hello,整个过程共四个阶段,由编译工具链完成,在这里我们来完整的看下对hello.c进行编译链接的四个过程。

第一过程:预处理(cpp),在命令行下输入gcc -E hello.c -o hello.i(gcc预处理)的命令,预处理器会对以#开头的预处理命令进行处理。譬如hello.c中的#include,预处理器会将系统中的hello.h的具体内容读取到文本中,替换原有的#include。得到一个新的C程序,我们一般称为.i文件,这里得到的hello.i文件格式如下:

Hello.i

...

...

extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));

# 943 "/usr/include/stdio.h" 3 4

# 2 "hello.c" 2

int main(int argc, char *argv[])

{

printf("hello world.\n");

return 0;

}

第二过程:编译(cc),在命令行下输入:gcc -S hello.i -o hello.s(gcc编译),当然也可以gcc -S hello.c -o hello.s,只是这种方式是由预处理器和编译器一起完成的,编译器将hello.i翻译成了hello.s汇编文件,汇编程序是一条条通用的机器语言指令。

hello.s

.file "hello.c"

.section .rodata

.LC0:

.string "hello world."

.text

.globl main

.type main, @function

main:

.LFB0:

.cfi_startproc

pushl %ebp

.cfi_def_cfa_offset 8

.cfi_offset 5, -8

movl %esp, %ebp

.cfi_def_cfa_register 5

andl $-16, %esp

subl $16, %esp

movl $.LC0, (%esp)

call puts

movl $0, %eax

leave

.cfi_restore 5

.cfi_def_cfa 4, 4

ret

.cfi_endproc

.LFE0:

.size main, .-main

...

第三过程:汇编(as),gcc -c hello.s -o hello.o(gcc汇编),汇编器会将hello.s翻译成机器语言指令,将这些指令打包成为***.o格式的可重定位文件,并将结果保存在目标文件hello.o中,目标文件是由不同的段组成,通常一个目标至少有两个段,数据段和代码段。hello.o用文本文档打开后是无法被看懂的,因为这是二进制文件。

第四过程:链接(ld),gcc hello.o -o hello.out(gcc链接),链接是最后一个过程,链接器会将hello.o和其它库文件,其它目标代码链接后形成可执行文件,在本程序中hello.c里调用了printf函数,链接器会将printf.o文件并入到我们的hello.out可执行文件中。最后将可执行文件加载到存储器后,然后由系统执行。每一个阶段产生的文件都是不同的,可以在Linux命令行下查看这四个文件的结果如下:

ls -l hello*

-rw-r--r-- 1 root root 97 Mar 8 01:31 hello.c

-rw-r--r-- 1 root root 17580 Mar 8 01:32 hello.i

-rw-r--r-- 1 root root 485 Mar 8 01:32 hello.s

-rw-r--r-- 1 root root 1024 Mar 8 01:32 hello.o

-rwxr-xr-x 1 root root 7292 Mar 8 01:33 hello.out

我们平时所说的编译器实质是指是编译工具链,预处理用预处理器(preprocessor) ,汇编用汇编器,链接用链接器,这几个工具再加上其他一些额外会用到的工具,合起来叫编译工具链。gcc就是一个编译工具链。

1.2、编译连接中各种文件扩展名的含义

在Linux系统中,分为可执行文件和不可执行文件,由源码到可执行程序的过程中,以扩展名(即后缀)来区分各个阶段。gcc中一些常见的扩展名,我们需要注意扩展名的写法及其背后的含义,否则编译失败。例如:后缀为.s和.S文件的区别?

gcc中一些常见的扩展名

扩展名 含义 扩展名 含义

.c C语言源代码文件 .m Objective-C源代码文件

.a 由目标文件构成的静态库文件 .o 编译后的目标文件

.C C++源代码文件 .out 链接器生成的可执行文件

.h 程序所包含的头文件 .s 汇编语言源代码文件

.i 预处理过的C源代码文件 .S 经过预处理、编译和汇编后的汇编源代码文件

.ii 预处理过的C++源代码文件

86e3834394fd2cc2074333597e6b7d1c.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值