从源代码到可执行程序

一切皆01

源代码 hello.c,
这里写图片描述

利用hexdump命令,可以看下hello.c到底是什么?
这里写图片描述

一串的二进制文件(用16进制表示),编码采用的是ASCII编码(二进制和字符之间的对应关系),通过下表,可以将hello.c中的字符和二进制对应起来,例如16进制的23是十进制的35,十进制35对应的正是’#’。

这里写图片描述

系统中的所有信息—包括磁盘文件(上面的hello.c),网络上传的数据等都是由一串比特表示的。区分不同数据对象的唯一方法是读到这些数据时的上下文。在不同的上下文中,同样的字节序列可以被解析为不同的整数、浮点数等。

从hello.c到hello

hello.c是从源代码到可执行程序的过程,可以分为下面几步:
这里写图片描述

下面逐步展开,首先是预处理

gcc –E hello.c –o hello.i

增加printf声明

这里写图片描述

上面两图是截取了hello.i中的部分内容,可以看到,预处理主要处理代码中以#开头的行

  • 预编译后源码从6行变到了850多行
  • 增加了printf函数的声明

接下来是编译

gcc -S hello.i -o hello.s

编译器将文本文件hello.i 翻译为hello.s,这个文件里面包含一个汇编程序,如下图所示,
这里写图片描述

无论是预编译、编译等,都是高级语言(c语言)向机器语言逐渐翻译的过程。

接下来是汇编

gcc –c hello.s –o hello.o

汇编器将hello.s 翻译成机器语言保存在hello.o 中

最后一步是链接

gcc hello.o –o hello

在hello.c中并没有定义printf的函数实现,且在预编译中包含进的stdio.h中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现printf函数的呢?
系统把这些函数实现都做到名为libc.so的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径/usr/lib下进行查找,也就是链接到libc.so库函数中去,这样就能实现函数printf了,而这也就是链接的作用。

经过上面的编译、链接等工序,生成了可执行程序hello
这里写图片描述

执行hello的shell窗口,也是一个程序,它是一种命令行解释器,它输出一个提示符,等待你输入命令,然后执行这个命令。如果命令行的第一个单词不是内置的shell命令,shell就会假设这是一个可执行文件的名字,要加载和执行该文件。

为什么需要库文件

在上述hello程序中,我们调用了标准c库中的printf函数,那么为什么我们需要这些库?

Why is library function needed?
1. They work
One of the most important reasons you should use library functions is simply because they work.
These functions have gone through multiple rigorous testing and are easy to use.
2. The functions are optimized for performance
Since, the functions are “standard library” functions, a dedicated group of developers constantly make them better.
In the process, they are able to create the most efficient code optimized for maximum performance.
3. It saves considerable development time
Since the general functions like printing to a screen, calculating the square root, and many more are already written. You shouldn’t worry about creating them once again.It saves valuable time and your code may not always be the most efficient.

为什么python在机器学习这些领域越来越火,其中最大的一个原因就是因为其庞大的生态圈和各种优秀的库文件

猜你喜欢

转载自blog.csdn.net/lewif/article/details/79831041