目录
(1). 程序的翻译过程
预处理: gcc -E 源文件
编译: gcc -S 源文件
汇编:gcc -c 源文件
连接:
(2) 语言的自举(也叫 编译器的自举):
(3). 查看可执行程序在连接时依赖的库: ldd 可执行程序的名字 。
(4). 函数库: 函数库一般分为 静态库 和 动态库
(5). 连接方式: 动态连接 , 静态连接。
(6). 编译:gcc 对 文件进行编译后, 生成的是可执行程序
(1). 程序的翻译过程
预处理(进行宏替换) , 编译(生成汇编) , 汇编(生成机械可执行代码) , 连接(生成可执行文件/库文件)
gcc的选项是 E , S ,c
预处理: gcc -E 源文件
gcc -E code.c -o test.i : 生成 预处理后的文件 test.i
预处理后文件中的内容还是c语言
编译: gcc -S 源文件
gcc -S test.i -o test.s : 生成 编译后的文件 test.s
开始进行程序的翻译, 形成汇编。此时 文件中的是 汇编代码
汇编:gcc -c 源文件
gcc -c test.s -o test.o : 生成 可重定位目标文件 test.o
文件中的内容是 二进制内容
连接:
gcc -o test test.o : 生成可执行程序
连接是 把 xxx.o 文件 和 标准库 进行关联, 构建可执行程序
-static 选项: 进行静态连接。 不加-static 默认是动态连接。
gcc -o test_static test.o -static
(2) 语言的自举(也叫 编译器的自举):
先有汇编语言 还是先有 汇编编译器? 答案是先有汇编编译器。 先用二进制 写一个 编译器 ,该编译器可以使得 汇编语言 翻译为 二进制(称这个为 二进制编译器)。 然后拿 汇编语言 来写一个 新的汇编编译器, 然后用 二进制编译器 , 编译形成一个全新的编译器。 这个过程叫做 语言的自举,也叫做 编译器的自举
(3). 查看可执行程序在连接时依赖的库: ldd 可执行程序的名字 。
此处的libc.so.6 是 test 可执行程序 依赖的库。 Libc.so.6 是 c语言标准库
如下图,ls命令 也依赖 libc.so.6库,证明 ls命令也是c语言写的。
一般命名中包含 .so 或以 .so 结尾 的库 是动态库。 显然 libc.so.6 就是一个动态库。
(4). 函数库: 函数库一般分为 静态库 和 动态库
动态库: .so (Linux) , .dll (windows)
静态库: .a (Linux) , .lib (windows)
云服务器默认没有按照c/c++的标准库的静态库
安装c语言静态库: yum install -y glibc-static
安装c++静态库: yum install -y libstdc++-static
(5). 连接方式: 动态连接 , 静态连接。
静态连接的前提: 有静态库
静态连接: 把我们要访问的方法实现,拷贝到我们自己的可执行程序中
i. 静态连接的优点:不依赖其他库,即使库丢失也无所谓,照样可以运行
ii. 静态连接的缺点:比较浪费资源。 形成的可执行程序的体积较大
动态连接的前提: 有动态库
动态连接: 记录我们要访问的方法实现的地址,访问时,通过地址跳转到对于地址来访问方法
i. 动态连接的优点: 比较节省资源。 形成的可执行程序的体积比较小
ii. 动态连接的缺点: 一旦动态库缺失,所有程序都无法执行。 即如果 libc.os.6 删除后,就无法运行用c语言写的程序了
查看文件是静态连接还是动态连接的方法: file 命令。 语法: file 文件名
即 dynamically linked (uses shared libs) 是动态连接。 statically linked 静态连接
(6). 编译:gcc 对 文件进行编译后, 生成的是可执行程序
选项: -o , 相当于是 将程序 生成为文件 并指定名称
gcc 编译并生成文件的语法:
gcc -o 生成的文件的名字 源文件 , 也可以写为 gcc 源文件 -o 生成的文件的名字
是把源文件 进行编译,然后把 编译后的可执行程序 命名为 此处的可执行程序的名字
然后执行可执行程序即可。
Eg: