欢迎来到 Claffic 的博客 💞💞💞
“ 石配树而华 ,树配石而坚 。”
前言:
在用C语言写代码前,我们会先创建一个或多个源文件(.c 文件),最终源文件会变成可执行文件(.exe 文件),你知道这期间经历了什么吗?听我细细讲解 ~
目录
第一 种是 翻译环境 ,在这个环境中 源代码被转换为可执行的机器指令 ; 第 二 种是 执行环境 ,它用于 实际执行代码 。
简单的图示
接下来我会给大家依次讲解这两个过程

如图,每个 源文件 单独经过 编译器 处理,生成 目标文件 ,所有目标文件与 链接库 一起,在 链接器 的作用下生成 可执行文件 。
演示:
创建一个项目,在这个项目下创建三个源文件:

内容如下:
//test.c
#include<stdio.h>
extern Add(int, int);
extern Sub(int, int);
int main()
{
int a = 20;
int b = 30;
int c = Add(a, b);
int d = Sub(a, b);
printf("%d\n", c);
printf("%d\n", d);
return 0;
}
//Add.c
int Sub(int x, int y)
{
return x + y;
}
//Sub.c
int Add(int x, int y)
{
return x - y;
}
运行后,
查看 .exe 文件:

查看 .obj 文件:


是不是与上述过程一样呢
一些细节:
• 组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code);
• 每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序;
• 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员 个人的程序库,将其需要的函数也链接到程序中。
我们已经知道了,源文件变成可执行文件需要编译和链接两个过程,那么编译本身有哪些阶段呢?
我是图示
由图示可看出:编译经历的阶段有 预编译 --> 编译 --> 汇编
接下来细讲每个过程:
注:由于 VS2022 属于集成开发环境,不方便展示细节,
所以接下来我会使用 Linux 环境下的 gcc 来演示编译和链接的过程。
为方便起见,我们只使用 test.c 和 Add.c 文件。
首先把刚才的代码写入文件:

这时我们只进行预编译
输入指令: gcc test.c -E (-E 就是预编译后停下来)
回车
会发现 预编译的结果直接输出在屏幕上了:
其实内容非常多,这里选取部分
我希望把 预编译的内容放在一个文件中
输入指令: gcc test.c -E -o test.i

此时就多了一个 test.i 文件
对 Add.c 进行相同的操作 gcc Add.c -E -o Add.i
打开相应的文件 vim test.i
有足足800多行代码:

这时会问了: 为什么预编译后出现了这么多代码?
回想一下,我们的 test.c 里面有什么内容来着?
#include<stdio.h>
没错,就是引了头文件,可以理解为: 在预编译过程中将相关的头文件进行了展开
于是就有了预编译的第一条操作:
• 头文件的包含
接下来我在 test.c 文件中加入以下代码:

重新预编译 test.c 到 test.i 中:
可以发现:MAX被替换,注释也消失了;
• define 定义符号的替换
• 注释删除
小总结:
预编译阶段中进行的操作:
• 头文件的包含
• define 定义符号的替换
• 注释删除
都属于 文本操作
我们接下来要做的就是让预编译后的文件只进行编译操作
输入指令: gcc test.i -S
可见生成了一个 test.s 的文件
打开 test.s :

可见里面是一些 汇编代码
其实这就是编译阶段的主要操作:
• 把C语言代码翻译成汇编代码
再深入些,
翻译的过程有:
1. 语法分析
2. 词法分析
3. 语义分析
4. 符号汇总
其实前三个过程比较好理解,就像我们读英语一样,要把英语转换成中文来理解。像这些分析,其实就是把C语言代码转换成汇编能理解的代码。
符号汇总就比较特殊,这里拿出细讲:
符号汇总,其实就是 把一个文件中那些全局的符号汇总到一起
比如:

红色方块部分是汇总出的符号
某种意义上,汇总的符号是函数的符号。那这有什么用呢?先不急,接着看。
进一步,令编译后的文件只进行汇编操作
输入指令: gcc test.s -c

又出现了新的 test.o 文件
打开 test.o :

嗯,看不懂。
其实是 二进制 啦 ~ 当然看不懂
那么 汇编的操作 也显而易见了:
• 把汇编指令翻译成二进制指令
其中又有一个重要的过程: 形成符号表
我们说了看不懂,那谁能帮我们看懂呢?
在 Linux环境下:
test.o 和可执行文件的格式是 elf ,理应, readelf 可以读
输入命令: readelf test.o -s

这不,汇总的符号就出现了。

形成符号表,其实就是把汇总出的符号赋予一个临时地址
链接链接,通俗来讲就是把多个文件连接起来
链接进行的操作:
• 合并段表
• 符号表的合并和重定位
合并段表解释:
前面提到 .o 文件和可执行文件都是 elf 格式,elf 格式本身具有段,
.o 文件在形成可执行文件的过程中会把相对应的段合并

图示
符号表的合并和重定位:
前面提到了形成符号表,并赋予了一个临时地址,
它们最终会 合并 到一起
对于出现一次的符号来说,地址可以直接用临时赋予的地址;
而对于出现多次的符号来说,地址不统一,就需要 重新定位 。

图示
总结:
听了 .c 到 .exe 的故事,是不是感觉 .c 到 .exe 道路有些艰辛呢?

一图总结
码文不易
如果你觉得这篇文章还不错并且对你有帮助,不妨支持一波哦 💗💗💗
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
Ocra无法处理需要“tk”的应用程序require'tk'puts'nope'用奥克拉http://github.com/larsch/ocra不起作用(如链接中的一个问题所述)问题:https://github.com/larsch/ocra/issues/29(Ocra是1.9的"new"rubyscript2exe,本质上它用于将rb脚本部署为可执行文件)唯一的问题似乎是缺少tcl的DLL文件我不认为这是一个问题据我所知,问题是缺少tk的DLL文件如果它们是已知的,则可以在执行ocra时将它们包括在内有没有办法知道tk工作所需的DLL依赖项? 最佳答
当尝试创建一个heroku应用程序并通过git推送到它时,我收到以下错误:$herokucreate'"C:\ProgramFiles\ruby-1.9.2\bin\ruby.exe"isnotrecognizedasaninternalorexternalcommand,operableprogramorbatchfile.但是,$ruby-vruby1.9.3p125[i386-mingw32]我已经检查了PATH环境,它肯定包含“C:\ProgramFiles(x86)\ruby-1.9.2\bin”。同样有趣的是,当导航到该目录时,它实际上并不包含名为ruby.exe的文件
提前说明一下,尽管标题看起来与线程RSpecvsCucumber(RSpecstories)相似,但是我的问题根本不同。我理解测试用户故事和单独测试对象行为之间的区别。我的问题是,为什么Cucumber通常与RSpec结合使用来编写用户故事,而RSpec从1.1开始就具有用户故事功能?是不是因为RSpec的重点仍然是单个对象测试,而Cucumber自那以后一直在大力开发,重点放在用户故事上?上下文切换是一件痛苦的事情,而我们开发人员需要处理足够多的工具。我宁愿只使用RSpec,但如果Cucumber与RSpec有一些重要区别,请告诉我。 最佳答案
我在WindowsVistaBusiness上使用GitBash。我正在尝试安装Redmine。基本上在第4步,我需要在安装bundler之前安装RubyGem作为依赖项安装的一部分(http://www.redmine.org/projects/redmine/wiki/RedmineInstall)。我从https://rubygems.org/pages/download下载了rubygems-2.2.2.zip.然后我将文件解压缩到桌面上的一个文件夹中。在GitBash中,我输入了rubysetup.rb,我得到了sh.exe:ruby:commandnotfound。
我是rbenv的新手(长期使用RVM)。今天我彻底卸载了我的RVM并安装了rbenv。我成功安装了Ruby2.5.1,没有任何问题。但是,当我今天尝试为一个项目运行bundleinstall时,出现了以下错误:'find_spec_for_exe':找不到带有可执行包(Gem::GemNotFoundException)的gem打包器(>=0.a)我的bundler安装似乎出了点问题,但我不确定哪里出了问题。使用sudo运行geminstallbundler无法解决问题。这是完整的轨迹:$echo$SHELL/bin/zsh$cat~/.gemrcgem:--no-documentin
所以我想开始使用RSpec故事,但我不确定编写Controller、模型和View规范的位置。例如,您有“登录”故事和“用户提供错误的密码”场景,难道您最终测试的不是与Controller/模型规范相同的东西(response.shouldrender...,user.shouldbe_nil等)所以我的问题是:对于那些习惯于使用RoR进行bdd(或故事dd)的人,您是否仍然编写模型/Controller规范?如果是这样,您遵循的工作流程如何(“第一个故事,然后缩小到特定规范”)? 最佳答案 如果您现在开始使用故事(而不是拥有大量遗
是否可以在Windows上将ruby脚本编译成.exe文件?我到处搜索并尝试了以下方法(看起来RubyScript2EXE、Shoes和Crate似乎都死了或被遗弃了。):http://ocra.rubyforge.org/http://exerb.sourceforge.jp/index.en.html我在Windows7Ultimate(64位)上使用Ruby1.8.7从一个干净的系统我这样做:从rubyinstaller.org安装RubyInstaller1.8.7-p358gem安装watirgem安装ocragitclonegit://github.com/snau
我是Windows上的Ruby程序员,试图从Wincmd切换到Cygwin,但无法执行Rubygems的批处理文件。我已经将任何bin目录填充到WindowsPATH环境中。变量,包括存储可执行文件的Rubybin。然而,gems是由ruby.exe本身调用的,这会导致以下POSIX路径问题:duddle@duddledan/cygdrive/c/Ruby/ruby-186-398/bin$gem-vC:\Ruby\ruby-186-398\bin\ruby.exe:Nosuchfileordirectory--/cygdrive/c/Ruby/ruby-186-398/bin/g
我的操作系统是windows7,我正准备将我的本地MySQL数据库连接到Heroku共享数据库,有一次,我得到了libmysql.dll文件丢失的错误,所以我搜索并下载了dll文件并保存它在ruby/bin目录中。当我再次连接时,这次它显示错误ruby.exe未被识别为内部或外部命令,这就是错误的样子。发送模式'"ruby.exe"'isnotrecognizedasaninternalorexternalcommand,TA:--:--:--operableprogramorbatchfile.'"ruby.exe"'isnotrecognizedasaninternalor