Index
前言
我看一些知识区内容时,发现很多逆天评论,今天讨论(没C语言啥软件都运行不了)。(本人并不排斥C语言)
程序究竟是如何运行的
大家都知道程序是通过二进制代码运行的,这个二进制代码根据不同的CPU架构对应的东西也不太一样,比如指令集x86,ARMv7,ARM64等等等,还有微架构好像不同与指令集架构(我并从事这方面的工作,所以并不了解具体区别)
总的来说,你可以理解为你需要调用CPU的接口,你写的程序被储存成了CPU接口调用序列和系统接口和框架格式,这样操作系统就可以把剔除格式后(这个过程本身也是操作系统的程序在调用CPU指令)的接口调用序列喂给CPU执行。(我不确定这个比喻是否准确)
这里面还涉及操作系统知识,或者你想了解操作系统或小型硬件上的程序,这涉及到ROM上的程序和相关接口,总的来说机器启动会执行一段完全由硬件实现或者是一个微型的ROM烧录的程序去启动各个硬件并读取和加载其它程序。(这个过程可能不止一层)
C语言究竟是如何运行的
如果你大学C语言第一节课,看了教科书那你应该大致了解C语言的执行步骤,我这里,告诉你你关心的,而不是定义的解释。
- 预处理:有的教科书里没写,这个程序就是先简单的格式化下代码还可以做下简单的优化。
- 编译:编译语言的核心,这一步,通常是把C语言编译成汇编语言,一个编译器牛不牛逼其实这一步是重中之重,优化也多在这一步。(但也有编译器跳过了这一步,直接编译成二进制序列。C语言编译器不同厂家不同标准的有很多!就这一条就可以看出来C语言并不是什么通用的东西。)
- 汇编:如果上一步的产物是汇编,才会有这一步,将汇编转化为机器代码。
- 链接:你可以理解为这一步是把你的程序和他运行的目标环境所需要的框架融合起来,这一步不同系统上的功能将完全不一样。
之后你得到了一个可执行文件,假如这个程序是针对操作系统编译(编译通常指上面四个步骤的组合)的你可以基于操作系统来运行它。你基于ROM编译的是不能通过操作系统执行的(或许操作系统有兼容?我想不会),因为操作系统会先检查它的格式,同理你基于操作系统编译的,也不可能直接在硬件上运行,除非你自己做的硬件或ROM程序无视了格式检查(会发生什么我并不知道,因为你的代码里包含需要操作系统处理的代码,我不知道CPU的防御机制是什么样的)。
上下文均是小说内容,无实际参考价值;IA护防懂都得懂
其它语言究竟哪些部分依赖C语言
没有任何语言的产物,最终运行在C语言之上,程序代码怎么可能运行在字符串之上?
下面我简单收集了下,主流编程语言的编译器或解释器或虚拟机的开发(并不是运行)对C/C++的依赖
语言 | 解释器/编译器型号 | 版本 | 依赖(版本懒得查了) | 备注 |
---|---|---|---|---|
Python | CPython(一般Python指的都是Cpython版本) | 所有 | C&汇编 | 实际上Python还有Java,C#,Python编译版本(未自举) |
JVM(Java虚拟机) | java官方和OpenJDK | 所有 | C&C++&汇编 | java工具链实际上也有各种奇怪的版本。java编译器和虚拟机是两个东西。java程序最终在虚拟机上运行。由虚拟机分析java字节码选择调用什么二进制指令。 |
.Net-CLR虚拟机(c#,vb,f#,c++.net等) | 一般所有 | .Net之后 | C++&汇编 | 古老版本不研究了 |
Golang | 官方 | <1.5(不包括) | C&汇编 | Golang1.5版本之后除cgo功能外(大多数场景都不需要CGO不是么)完全脱离c语言 |
Rust | 官方 | 所有 | C&C++&汇编 | Rust有计划脱离C但没有排期(狗头) |
可以看到.Net的虚拟机也用的C++,并不是C语言。
自编译:自举(self-hosting)
我本来还想多举几个例子,但主流语言均没有做到和C/C++/Golang一样可以除汇编外自举,不主流的也不多。
自编译的意思就是可以用自己的编译器编译新版本的自己的编译器,注意Golang的CGO功能是用链接器实现的,Go语言中调用和类型转换部分是由Go编译器实现的。
比C语言更早的编程语言
我就不列举了,问AI就行了,我问的有八个。C自举前是用B语言开发的,C++自举前是用C语言开发的。
在那之前,系统层技术债务
我不确定windows系统或者类unix系统(移动操作系统都属于类unix系统)和主流物联网系统(我不了解),有没有这种把.h文件放着或者什么逆天功能需要动态编译才能执行的。以我对软件行业的了解,至少存在需要在安装时编译一次的应用层软件,但我查了Claude-3.5-Sonnet 20241022-API版本,回答的是windows安装时完全没有这种情况,linux发行版也有无需编译安装的版本(但我认为AI可能理解有问题,但我又没时间去看这些代码。不要以为有人就专业,我接触过大厂资深系统运维,我不觉得他们人人都很专业。实际上我昨天写的代码,今天可能就看不明白了,系统的开发人员可能也需要长时间检查才能准确的回答你的问)(相信我,如果对答如流,那他一定是今天刚做完这个工作,否则要么在瞎扯,要么就容易出错,或者这个问题他遇到了一百次,但你有没有想过这一百次他的理解都是错的,他解决了问题,但用了错误的方式或他不理解的手段)。
但假如神说,禁用C语言,确实有可能出现瘫痪的情况,但这属于"BUG",并不是本来就应该是这样子的
神说不许再写一行C语言代码
- 不会影响的(理想情况,实际情况因为技术债务也会存在影响):
- 每周应用商店更新的几十个应用
- 大多数软件的热更新
- 不断变化和层出不穷的广告
- 会影响的:
- 多数专业软件停止更新
- 一旦出现严重底层漏洞将出现灾难
- 底层软件全面停更,全部重构是一个漫长的周期(然而rust真的集现代软件工程大成了么,我觉得没有,还不是重构的时候,更何况rust连自举都没做到现在)
上下文均是小说内容,无实际参考价值;IA护防懂都得懂
什么是汇编
汇编最早出现就是机器指令的代记符
直到今天汇编中仍然有大量指令和机器指令是一一对应的,但也出现了一些集成功能和性能优化和完全转义。
汇编不同平台上的版本差异巨大,每个不同的CPU平台都要定制自己的汇编版本,不同的架构更新后也会推出新版的汇编工具链。
汇编代码转换为二进制代码的过程,一般称为汇编而不是编译。
你有没有想过所有的抽象概念实际上都是二进制序列
只要你用的是现在主流的二进制计算机结构的硬件,那所有的抽象概念,什么汇编,什么语言,操作系统,ROM里的程序,本身就是二进制序列,它不是你看到的东西,只是经过了复杂的程序,把数据送到了你的显示设备上,经过很多不同的程序让你看见。
甚至你的眼睛接收的也不是你想象的概念(当然这里或许就不是二进制了)。
我最后又想到小白犯错的一点,分清编辑器和编译
- 编译:把高级语言代码转化成二进制或汇编代码的过程。(今天也被用来代指两种高级语言代码之间的转化,用的人多,我也不好反驳)。
- 编译器:实现编译的工具或工具的一部分。
- 编辑器:一个让你编辑某种文本编码(例如UTF8)的软件。
- IDE(集成开发环境):一个功能强大的编辑器,早期往往在安装时集成了编译和测试工具链,但今天jetbrains的很多IDE都是在第一次创建项目的时候选择已有工具链或下载一个新的。而且VSCode的强大和极客开发者对VIM的改造,IDE和编辑器的概念或许已经混稀了。