前言:
在上一篇,我们学习了关于文本编辑器 vim 的全部知识,今天给大家带来的是关于Linux编译器—gcc/使用的详细介绍。

本文目录
通过之前的学习,我们可以知道在 Linux 下编写C\CPP 程序时,在完成 .C 或 .CPP 文件的编写后,我们通常直接 gcc 或 g++ 后接文件名,就可以在当前文件夹下生成 a.out 可执行文件, 之后输入 ./a.out 即可执行该二进制可执行文件。

但实际上C语言程序从编写到运行,这期间的经历并不是这么简单,接下来我就带领大家对其探索一番,这期间具体有哪几个步骤?
从之前的知识来说,我们应该都知道程序的翻译经过几个阶段。我们会历经三个步骤,分别是:【预处理阶段】——>【编译阶段】——>【链接阶段】。但是如果我们分的更细一点,其实我们可以分成四个步骤:

通常 gcc 命令后面不加选项的话,就会默认执行 预处理、编译、汇编、链接所有步骤,若程序没有错误的话,我们就可以得到一个可执行文件,默认为 a.out, 也就是上述我代码中出现的。
有了上述的铺垫之后,接下来我们讲讲什么是 gcc吧!!先让大家有了认识,以便我们后序的深入学习。
gcc 是一个常用的 C 语言编译器,可以将源代码转换成可执行程序。 使用 gcc 编译器需要以下步骤:
格式为:gcc <源代码文件名>.c -o <输出文件名><源代码文件名><输出文件名> 例如,编译名为 的 C 语言源代码文件,并将其输出到名为 的可执行文件中,可以使用以下命令:hello.c hello
gcc hello.c -o hello
//加入-o选项的意义在于你可以指定输出二进制文件的名字
有了上述的前情铺垫之后,接下来我们具体的讲讲各个阶段到底是是怎么样的!!
首先第一步就是预处理阶段,在这个阶段主要主要执行的包括以下四个步奏:
举例说明:
其中预处理阶段是把代码中的【#】开头的命令进行相应的处理,例如:
💥gcc执行指令
gcc -E test.c -o test.i
1 #include<stdio.h>
2 #define MAX 1000
3
4 int main()
5 {
6
7 printf("hello world\n");
8
9
10 int m = MAX;
11 printf("%d\n",m);
12
13 printf("hello world\n");
14
15 // printf("hello world\n");
16 // printf("hello world\n");
17 // printf("hello world\n");
18 // printf("hello world\n");
19 // printf("hello world\n");
20 // printf("hello world\n");
21 // printf("hello world\n");
22
23
24
25 return 0;
26 }
经过 命令之后就变成了这样

💨选项
预处理阶段过后紧接着就是编译阶段。这个阶段处理的就是c语言的汇编语言,它主要处理的包括以下:
注意:
💥gcc执行指令
gcc -S test.i -o test.s
👉 其实【gcc】在执行编译命令的时候会带上预处理,然后不保存过渡用的预处理出来的【.i】文件,所以编译时候的输入还是你写的【.c】文件,如果想看一看预处理结果的话才用【-E】指令;
👉 其次如果我们直接用原始【.c】文件来编译一下也可以,用刚生成的【.i】文件编译也是可以的,命令是【gcc -S test.i -o test.s】(我这里默认的是从上次结束的地方继续执行)
👉 最终结果是一个汇编程序的文件,注意这里输出的仍然是一个文本文件。

💨选项:
编译阶段过了之后,紧接着就是汇编的执行阶段。在这个阶段,它做的主要有以下的事情:
💨将汇编指令转换为二进制文件
💨 形成符号表
💥gcc执行指令
gcc -c test.s -o test.o
👉 汇编就是把编译出来的汇编文件打包成一个二进制文件,里面存的都是机器指令.gcc的命令是【gcc -c test.s -o test.o】, 得到的结果是个【.o】文件,这个文件是不能用人类语言解读的,打开发现是一堆乱码

👉 此时当我们想来试着执行一下这个目标文件时,不过发现没有【x】可执行的权限,于是使用chmod做一个提权的操作。
👉 但是系统却说【cannot execute binary file】因为这是一个二进制文件,对于二进制文件来说是不可以被执行的。

💨选项:
最后,即是链接操作了,在这一步主要做的事是:
💥gcc执行指令
gcc test.o -o test
👉 检查刚才的【.o】文件,查看它引用的其他【.o】文件,比方说【printf】函数就是C语言的库函数,她在一个单独的【printf.o】文件里,这个文件在 gcc 的目录里面,和我们现在创建的工程没有关系,所以看不见;
👉 但是它会去库中找这个文件,所以链接就是找到它,然后把他们集成到一个可执行程序里
最后,我们打印一下最后的文件,看是否能够正常的运行并且输出对应的结果:

⌨️命令选项 :【-E】 【-S】 【-c】——>键盘上左上角的键(注意 s 要大写)
⌨️文件后缀 : 【.i】 【.s】 【.o】——>iso为镜像文件的后缀
文件后缀:

命令选项:

此时,不知道大家知不知道我们为什么能够在【Linux】在进行C、C++代码的编写和编译呢?
首先,我们先编写【.Cpp】程序试试看在【Linux】上是否能够运行!

运行结果如下:

👉 上述我们可以发现,对于【.cpp】程序一样是可以的。那么到底是为什么呢?是怎么实现的呢?
👉 我们先来看看系统中的头文件所在目录,然后就可以发现我们熟悉的头文件名【stdio.h】等

👉 头文件是告诉我们使用的方法,通过头文件的方式把方式告诉我们,其次也在告诉编译器,头文件是否有,只要有头文件就有源文件。
ldd本身不是一个程序,而仅是一个shell脚本:ldd可以列出一个程序所需要得动态链接库
我们可以用which命令找到ldd的位置:

格式:
ldd(选项)(参数)
👉 紧接着我们就可以去看看刚才【g++】之后最终链接后形成的【a.out】这个可执行程序都依赖了哪些库。

🔥 注意:
在 ldd 命令打印的结果中:
“=>” :左边的表示该程序需要连接的共享库之 so 名称;
右边表示由 Linux 的共享库系统找到的对应的共享库在文件系统中的具体位置。
因此,在此就解答了上述的问题为什么可以在【linux】下编写代码了!!!
此时,有衍生出来了一个问题——>那就是大家知道我们平时写代码的【vs2022】啊还是【vs219】或者其他的,当我们刚开始安装它的时候,实际上帮我们完成的最重要的工作是什么吗?
紧接着,我们在【linux】下是不是纯手工的方式进行操作啊,用的全是指令,那么这些指令怎么来的呢?
我举几个例子带大家见识见识:



👉 综上所述:
我们可以看出在【linux】下,不管是 指令、工具、还是程序 等都是通过C语言写出来的!!!
首先,在学习之前,我们肯定地需要知道什么叫做动静态库。因此,第一步我们先认识静动态库:
💨 静态库:
💨 动态库:
1、🌜 代码被载入的时刻不同🌛
2、🌜大小与共享的差异🌛
2、🌜程序编译的差异🌛
在常用的指令中我们有说到过【file】指令,这个指令的作用是可以用来查看一个文件的类型,接下来我们就去瞧瞧这个动态的可执行文件

那这时就有小伙伴要问了?那我们如何实现静态链接呢? 其实很简单,只需在最后加上 【-static】即可。
但是如果大家没有安装静态库,此时你在你在执行以下代码的话就会报错(云服务器默认使用的是动态库)
(sudo) yum install -y glibc-static(sudo) yum -y install libstdc++-static演示如下:

所以大家知道为什么云服务器默认是安装的动态库了吧!!!

💥 静态库
💥 动态库
有关动静态库的更多知识,我们将在后面进行补充讲解!
到此,本文的内容便讲解完毕!最后,我们对本期内容做个小结!!!
以上便是本文的全部内容了,感谢大家的支持!!
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po