c语言程序的特点与执行过程,c语言程序的执行过程(以输出hello,world为例)

1.c源文件的存储

任何数据在计算机中都以二进制的样式进行存储,即0和1两种存储表示,那么c源文件中的各种字符要想存储在计算机中作为可执行的指令,那么必须得以二进制0或1的形式存储在其中,因此,需要将c源文件的需要被以某种方式“翻译”成二进制存储进计算机。数据类型表示数字的类型如int,double 等类型在内存中是以换算的二进制存的,而字符类型等在内存中是以ASCII存的,这个通过查ASCII得到相应的二进制,然后存放于内存。

比如:32767 当作int型 为整数,利用除2取余法得到相应的二进制数存于内存(本来应该存补码,但是正数的补码和原码相同)所占的内存空间跟其对应的数据类型有关,可能还与机器有关,

而32767 当作字符 即“32767”,这时应该分解‘3’,‘2’,‘7’,‘6’,‘7’,然后查对应的ASCII码 对应的值为:0011001 00110010 00110111 00110110 00110111 所以在存放的即为该二进制的组合,且占5个字节的内存

将指定的字符“翻译”成对应二进制文件需要“统一”的“密码本”,使得在任何一台计算上c源文件都以相同的二进制形式存储。而翻译这个c源文件的“密码本”就是ASCII码。

ASCII使用8位二进制数表示256个字符,这些字符包括32个大小写字符,10个数字,以及其他的字符,例如,一个输出“hello,world”的ASCII为#include

int main(void)

{

printf("hello,world\n");

return 0;

}

2eee5e5f6da264084cafb62518a86ed2.png

即符号#的ASCII码为35,i的ASCII为105......

而ASCII中35的二进制为0010 0011,i为0110 1001......

因此c源文件在计算机中存储为0010 0011 0110 1001 ......

2.c源文件的编译

Linux系统上的编译hello.c:

018db7b4b65de8695643cdd1ff87dd8f.png

c源文件仅仅是以二进制的形式存储在计算机中,而我们要实现的是计算机输出“hello,world”,那么需要将这些二进制文件编译成计算机可以识别的指令,“告诉”计算机我们要输出“hello world”。

构成这些计算机可以识别的二进制指令称为机器语言,因此,c语言的编译就是编译成机器语言共计算机执行。

在Linux系统中,将c源文件编译成可执行的二进制指令文件是由gcc编译器完成的,gcc是gnu组织的开发的编程语言编译器。

输出“hello,world”的hello.c的编译流程:

93f8ddafbbd178f3b9a5070184a2e37f.png

编译一个hello.c的程序总共分为四个阶段:预处理,编译,汇编和链接

预处理阶段:预处理阶段是根据程序中字符#开头的命令并执行相关操作,在holle.c中#开头的第一行为#include ,预处理器就读取c库中的stdio.h的内容将其插入到hello.c文本中生成一个新的文件hello.i;

编译阶段:编译器ccl将hello.i翻译汇编程序储存在文件hello.s中,其中的main作为一个函数给出了机器语言的输出指令;.file"hello.c"

.section.rodata

.LC0:

.string"hello,world"

.text

.globlmain

.typemain, @function

main:

.LFB0:

.cfi_startproc

pushq%rbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

movq%rsp, %rbp

.cfi_def_cfa_register 6

movl$.LC0, %edi

movl$0, %eax

callprintf

movl$0, %eax

popq%rbp

.cfi_def_cfa 7, 8

ret

.cfi_endproc

.LFE0:

.sizemain, .-main

.ident"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"

.section.note.GNU-stack,"",@progbits

汇编阶段:汇编器将hello.s中的汇编语言翻译成计算机可以识别的机器语言存为hello.o二进制文件;

链接阶段:在c源文件中我们引用了printf打印函数,而计算机要识别这个函数也要由二进制指令组成。而在头部文件中stdio.h作为c语言的标准库,其中已经定义了printf的接口,系统根据接口去读取已经写好的printf.o二进制指令文件,将其与hello.o文件合并为hello二进制文件,称为可执行目标文件或可执行文件。

3.hello文件的执行过程

Linux上执行hello打印输出:

ffd850bb85a597b909d14c65c141ad9a.png

打开shell从键盘输入./hello,shell会优先把输入的字符串当做内置命令,若不是则会将其当做可执行文件的名字处理。shell将计算机I/o接口连接的输入设备输入的字符串通过总线接口存入寄存器,再存入内存中。

从键盘中读取shell命令流程:

98740c583e703cfc91f1c35422f47908.png

完成./hello输入后,当从键盘上输入回车后,shell得知命令输入完成,开始执行一系列指令从磁盘复制hell文件到内存中,流程如下:

78e42802db93352bee2c0213f7fd5c2c.png

当hello文件被复制到主存之后,处理器开始执行hello程序的main程序的指令。流程是将这些指令从主存复制到寄存器,再从寄存器复制到显示设备上,最终显示到屏幕上,流程如下图:

d09e8cdddb1b204ad9f9cad809597cc4.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值