【Linux入门】Linux编译器gcc/g++基础

目录

  • 1.背景知识
  • 2.gcc/g++的用法
  • 3.指令补充
    • 3.1.ldd指令
    • 3.2.file指令
  • 4.Linux下的头文件、库
    • 4.1.指令的库
      • 4.1.1.动态库
      • 4.1.2.静态库
      • 4.1.3.动静态库的优缺点
  • 5.gcc/g++静态链接与动态链接的方法
  • 6.静态库的安装

1.背景知识

注:本篇的myfile只是为了方便讲解自己起的文件名。

gcc/g++是编译器——将文本文件翻译为二进制可执行文件。

程序的翻译可分为四个阶段:

  1. 预处理(头文件展开、条件编译、宏替换、去注释等,处理完还是c语言)
    用gcc -E myfile.c -o myfile.i生成myfile.i,对比可发现.i文件比自己写的.c文件要多很多,多出的内容是将头文件中的内容拷贝到了源文件中——头文件展开。
  2. 编译(检查语法,生成汇编)
    用gcc -S myfile.i -o myfile.s生成mufile.s,打开可发现代码又从.i的大文件变小了——生成了汇编
  3. 汇编(生成机器可识别代码:汇编 -> 可重定位目标二进制文件bin.obj,且不可执行
    ——只把我们自己的代码进行翻译形成二进制文件。
    用gcc -c myfile.s -o myfile.o生成mufile.o,.o为目标二进制文件(与windows下的.obj对等),打开会发现都是乱码,并且不可执行。
  4. 链接(生成可执行文件或库文件)
    ——将我们自己的代码形成的.obj文件和库文件进行合并,形成可执行程序
    用gcc myfile.o -o myfile生成myfile(不用-o指定则会默认生成a.out),myfile为可执行文件。

【Linux入门】Linux编译器gcc/g++基础_第1张图片


补充:
1.有几个源文件(.c)就生成几个.obj文件;
2.头文件(.h)则在预处理阶段就合并到源文件的特定位置中了(头文件展开);


2.gcc/g++的用法

1.格式:gcc [选项] 要编译的文件 [选项] [目标文件]
如果不加选项对文件直接使用gcc,比如gcc myfile.c会把程序翻译的四个阶段一次直接走完,生成一个a.out可执行文件,可以直接使用 ./a.out 对其进行执行。

[选项]:

  1. -o :将生成的文件输出到指定名称的文件中。(-o后面必定跟自己想生成的文件名) 用法:gcc -o myfile myfile.c或者gcc myfile.c -o myfile,将gcc生成的a.out输出到myfile中。

  2. -E :进行程序的翻译,但是在预处理结束就停止。 用法:gcc -E myfile.c -o myfile.i,将预处理生成的文件输出到myfile.i中。

  3. -S :进行程序的翻译,但是在编译结束就停止。 用法:gcc -S myfile.c或gcc -S myfile.i,从.c文件或从.i文件执行都可以,默认输出到myfile.s文件。 也可以gcc -S myfile.c -o
    mufile.s或gcc -S myfile.i -o mufile.s显式写出输出到.s文件中。

  4. -c : 进行程序的翻译,但是在汇编结束就停止。 用法:gcc -c myfile.c或gcc -c myfile.i或gcc -c myfile.s,从.c、.i、.s文件执行都可以,默认输出到myfile.o文件。 也可以gcc -c
    myfile.c -o mufile.o或gcc -S myfile.i -o mufile.o或gcc -c
    myfile.o显式写出输出到.o文件中。


3.指令补充

3.1.ldd指令

指令补充:

  • ldd : ldd [可执行程序],查看可执行程序依赖了哪些库(只能看动态链接的库

3.2.file指令

指令补充:

  • file :file [选项] 文件或目录,可以查看文件的类型
    [选项]:
    -c 详细显示指令执行过程
    -z 尝试去解读压缩文件的内容

4.Linux下的头文件、库

为什么在Linux下可以进行C\C++代码的编写与编译呢?
因为Linux已经携带了语言级别的头文件语言对应的库

  1. 头文件
    在Linux下,头文件一般在/user/include目录下。
  2. 库(Linux下)——使用 ldd [可执行文件] 可以查看程序链接库的地址
    库分两种,静态库和动态库。库的名字是去掉前缀lib、去掉后缀.a/.so剩下的
    静态库:libXXX.a (windows下为.lib)
    动态库:libXXX.so (windows下为.dll)
    例如:查看ldd myfile ,其中有一行会显示libc.so.6 => /lib64/libc.so.6,此时ls /lib64/libc.so.6 -al查看文件的详细信息,会显示 /lib64/libc.so.6 -> libc-2.17.so发现这个库的名字是c-2.17,这个库就是c语言的c标准库

(我们在windows下使用vs,安装软件时最重要的就是下载安装语言的头文件和库!)


4.1.指令的库

在Linux下,我们所使用的指令,相当一部分都是用C语言写的。

例如:
我们使用which ls查看ls的文件地址为/user/bin/ls,然后使用ldd
/user/bin/ls查看ls文件的库,可以发现其中也有libc.so.6 =>
/lib64/libc.so.6 C语言库,ls也是使用C语言写的。
【Linux入门】Linux编译器gcc/g++基础_第2张图片
也可以使用上述流程去查看别的指令的库,可以发现大部分语言都是使用C语言写的。

所以其实指令也是程序,和我们自己写的程序没有本质区别。


4.1.1.动态库

动态库 == 共享库
动态库被所有程序所共享,所以一般只有一份,并且具有只读属性,不允许别人修改。
如果动态库被删除,所有依赖这个动态库的程序都将无法正常运行
在链接器链接的时候,只需要把库中对应程序的地址填到所需的地方就完成了链接。

4.1.2.静态库

将所需要的代码直接拷贝到自己的程序中。
连接成功后,如果库被删除,程序依旧可以运行。


4.1.3.动静态库的优缺点

动静态库的区别:
静态库–>拷贝所需代码本体–>直接在自己的程序中运行–>静态链接成功就不再依赖库,独立运行,库缺失也可运行。
动态库–>拷贝所需代码地址–>运行时需要跳转到库中–>动态链接成功还是需要依赖库,库缺失不能运行。
静态库:因为是拷贝代码本体,所以比较浪费空间。
动态库:因为可以被共享,永远在库中,程序中只有地址,比较节省空间。


5.gcc/g++静态链接与动态链接的方法

Linux默认使用的是动态链接与动态库!
如果想使用静态链接,要在编译时使用-static选项:

  • -static :使用静态链接库

例如:
gcc myfile.c -o myfile_static -static(myfile_static是自定义文件名)
此时生成的文件,使用ldd myfile_static是无法查看链接了哪些库的;
使用file myfile_static查看文件信息,可以看到这个程序是静态链接的。

6.静态库的安装

一般的云服务器,默认都只有动态链接
使用yum install glibc-static libstdc++-static -y可以进行c、c++静态库的安装。
(或者sudo执行)

你可能感兴趣的:(linux,运维,服务器)