计算机程序(英语:ComputerProgram)是指一组指示电子计算机或其他具有消息处理能力的电子设备每一步动作的指令,通常用某种程序设计语言编写,运行于某种目标体系结构上。
打个比方,一个程序就像一个用汉语(程序设计语言)写下的红烧肉菜谱(程序源代码),用于指导懂汉语的人(体系结构)来做这个菜。计算机程序是软件的一个组成部分,它还包括文档和其他无形组成部分。通常,以英文文本为基础的计算机程序要经过编译和链接而成为一种人们不易看清而计算机可解读的一连串数字的格式,然后放入运行。这种程序也叫作编译语言。未经编译就可运行的程序,通常称之为脚本程序(script)或解释型语言。
源代码(英语:Sourcecode),是指一系列人类可读的计算机语言指令[1]。在现代程序语言中,源代码可以是以书籍或者磁带的形式出现;但最常用的格式是文本文件,这种典型格式的目的是为了编译出计算机程序。计算机源代码的最终目的是将人类可读的文本翻译成为计算机可以执行的二进制指令,这种过程叫做编译,通过编译器完成。
1.编译器、汇编器与解释器代码:nothingbutatextfilethatmakessense,whatmakethecodesensibleisthecompiler!编译器(compiler)是一种计算机程序,它会将某种编程语言写成的源代码(原始语言)转换成另一种编程语言(目标语言)。编译:将一段高级语言代码(如c语言)通篇翻译成低级语言(如汇编语言)代码的过程。
编译执行:代码经过编译变成汇编语言,然后经过链接(添加各种库),最终由汇编器生成机器码,也就是可执行文件,在Windows下的可执行文件叫做.exe
预编译:将hello.c和stdio.h预编译为hello.i编译:将hello.i编译为hello.s汇编:将hello.s翻译为机器指令hello.o(.o目标文件)链接:链接各种需要的库和其他目标文件(该hello程序不需要)得到可执行文件hello.out(相当于windows的.exe)
解释执行:将一段高级语言代码逐行编译,每编译一行就立即执行,不生成中间文件
编辑器就是处理文本(源码)的程序,写代码写的就是文本,编辑器可能提供智能提示、代码高亮等辅助功能,但不负责源码到二进制文件的操作;
编译器(compiler)就是负责将源码文本翻译成计算机能够理解和执行的二进制文件的程序;
集成开发环境(IDE,IntegratedDevelopmentEnvironment)是用于提供程序开发环境的应用程序,包括了代码编辑器、编译器、调试器和图形用户界面工具。集成了代码编写、分析、编译、调试等一整套工具链。
编译工具我们选用gcc(全称GNUCompilerCollection意思是GNU编译器套件),不过不是原版的gcc,而是它在Windows下的特制版MinGW(全称MinimalistGNUonWindows)。它实际上是将GCC移植到了Windows平台下,并且包含了Win32API,因此可以将源代码编译为可在Windows中运行的可执行程序。而且还可以使用一些Windows不具备的,Linux平台下的开发工具。MinGW又分为MinGW-w64与MinGW,区别在于MinGW只能编译生成32位可执行程序,而MinGW-w64则可以编译生成64位或32位可执行程序。MinGW现已被MinGW-w64所取代,且MinGW也已停止了更新。
MinGW,即MinimalistGNUForWindows。它是一些头文件和端口库的集合,该集合允许人们在没有第三方动态链接库的情况下使用GCC(GNUCompilerC)产生Windows32程序。
实际上MinGW并不是一个C/C++编译器,而是一套GNU工具集合。除开GCC(GNU编译器集合)以外,MinGW还包含有一些其他的GNU程序开发工具(比如gawkbison等等)。
开发MinGW是为了那些不喜欢工作在Linux(FreeBSD)操作系统而留在Windows的人提供一套符合GNU的GNU工作环境。
3.常见编程语言及对比cPython:Python社区的标准是CPython实现,是C语言写的。
还有一些其他的实现,比如PyPy,简单说是RPython实现的。
主流的就是上面这两个了,还有JVM实现,以及微软的实现。都比较小众了,没什么人用。bootstrap自举,用自己给自己写编译器
,JVM,pythonbytecode,c语言这么厉害,那它本身又是用什么写的?(先有鸡还是先有蛋)语言本身只是一段文本,真正让一段代码有意义的是编译器(你如何看待这一段代码)。C语言有意义的不是那一段用CProgrammingLanguage规则写成的文本,而是懂得规则的C语言编译器把这段文本按某种机制准确翻成C语言想要代指的汇编代码!
理解这个问题的关键,是认识到:编译器,只是读取文本文件(源代码),输出某种计算机编码(比如机器语言)的程序。
既然编译器也只是个普通的程序,那么就能用任何语言编写。所以,理论上来讲,你可以用Python、Java或者Scratch来写个C语言编译器【捂脸】。
换句话说只要有一个东西(不管他是什么),只要能帮我把C语言写成的那段字符串,转换成一个能在CPU上运行的程序,那就够了,我可以不用管这个"东西"是什么。是另一个程序,还是一个人手工翻译然后手动烧录CPU指令;是用C语言写成的程序,还是用JS写成的……我都不用再关心了。
第一个汇编器到第一个汇编语言写的C语言编译器到第一个C语言写的C语言编译器
编译器isnothinbut一个.exe罢了,这个.exe的功能是把C语言写成的文本转换成汇编语言的文本汇编器也一样,nothingbuta.exe,其功能是把汇编语言写成的文本转化成二进制的文本。
C语言编译器就是用来编译C语言的,如果C语言编译器也是C开发的,那么是先有C还是先有C编译器?没有C哪来的C编译器?没有C编译器又怎么去编译C?先有鸡还是先有蛋的问题
“C语言编译器是用C语言开发”这句话的正确理解应该是这样的一个过程:
操作系统有内核,而shell就是壳,壳把核包住,并连接核与外面的世界(用户)shell是用来解决用户(外面的世界)如何与操作系统(核)通信的问题。
Linux的核叫kernel,壳有很多种,有命令行的:bash、sh、csh、ksh,有图形化的:KDE、GNOME、CDE、XFCE,据说Linus那伙人只负责开发核。
Windows9X系列的核是DOS,图形化的壳叫WindowsExplorer,命令行壳叫command。从WindowsXP开始,Windows的核叫做WindowsNT(WindowsNewTechnology),图形化壳叫WindowsExplorer(就是Windows的文件管理器),命令行壳有command、cmd.exe,后面还推出了WindowsPowerShell。由于WindowsNT技术是针对图形化壳设计出来的核,而Windows9X就是在DOS上加了一个壳。所以WindowsXP蓝屏情况比Windows9X少得多,但也有。另外我见过Windows7蓝屏,且到目前为止没有见过Windows8和Windows10蓝屏。
实际上不管是命令行shell还是图形化shell,都是访问操作系统中的某个具有一定功能、可以处理具体事务的文件(二进制文件----此类文件经常被称作工具)、或包含一定内容的文件(文本文件),通常都是通过文件名访问(当然有例外,比如Linux的alias命令,比如通过链接文件访问源文件),所以通常文件名就成了命令。
在Linux的/bin目录和/usr/bin目录中有Linux命令对应的文件,在Windows的%windir%目录即操作系统安装硬盘分区的Windows目录和%windir%\system32目录中有Windows命令对应的文件,此外还可以引入外部命令和自定义命令。而shell的作用就是解释某条命令对应的文件的文件路径,供用户使用并返回使用结果。这也就是为何有shell脚本一说。脚本语言是种解释型语言,不能编译成二进制代码,区别于编译型语言。就如shell,它的作用是将命令解释成对应的文件名,然后通过文件名调用文件。对于图形化shell是通过鼠标的点击来访问文件的,但实际也是通过文件名,因为每个文件都有包含文件名的完整路径。
我们都知道在Shell中输入catlog.txt命令就可以查看log.txt文件中的内容,然而,log.txt放在磁盘的哪个位置?分成了几个数据块?在哪里开始?在哪里终止?如何操作探头读取它?这些底层细节Shell统统不知道的,它只能去调用内核提供的open()和read()函数,告诉内核我要读取log.txt文件,请帮助我,然后内核就乖乖地按照Shell的吩咐去读取文件了,并将读取到的文件内容交给Shell,最后再由Shell呈现给用户(其实呈现到显示器上还得依赖内核)。整个过程中Shell就是一个“中间商”,它在用户和内核之间“倒卖”数据,只是用户不知道罢了。
脚本小子(英语:scriptkiddie)是一个贬义词,用来描述以“黑客”自居并沾沾自喜的初学者。脚本小子不像真正的黑客那样发现系统漏洞,他们通常使用别人开发的程序来恶意破坏他人系统。通常的刻板印象为一位没有专科经验的少年,破坏无辜网站企图使得他的朋友感到惊讶,因而称之为脚本小子。
脚本小子常常从某些网站上复制脚本代码,然后到处粘贴,却并不一定明白它们的方法与原理。他们钦慕于黑客的能力与探索精神,但与黑客所不同的是,脚本小子通常只是对计算机系统有基础了解与爱好,但并不注重程序语言、算法和数据结构的研究,虽然这些对于真正的黑客来说是必须具备的素质。
因为自己研究和开发能力不够,脚本小子通常使用网上能够下载到的攻击程序。常见的这种软件有WinNuke、BackOrifice、NetBus、Sub7、Metasploit、ProRat、SQLmap、Havij。稍微有一点经验的脚本小子,可能使用别人发现的安全漏洞的概念证明代码,来编辑成程序。
命令行界面(CLI)=使用文本命令进行交互的用户界面终端(Terminal)=TTY=文本输入/输出环境控制台(Console)=一种特殊的终端Shell=命令行解释器,执行用户输入的命令并返回结果
我之前很迷惑一个问题是,有终端就够了嘛,输入命令,执行并把结果输出,要shell干什么。更让人抓狂的shell还有很多种类,bash,cshell,zsh。这些到底是做什么的?
所以需要明确下终端负责的工作。
终端的工作范围:接收用户的输入,显示传过来的输出。(此外还提供一些优化用户体验的功能,比如支持文字复制粘贴、软件背景颜色的调整等)
终端的工作其实是很少的哦,简单来说3点:GUI软件界面、接收输入、显示输出。
而shell的核心工作就是操控计算机内核(如新建文件等等),即访问操作系统中的某个具有一定功能、可以处理具体事务的文件(二进制文件----此类文件经常被称作工具)、或包含一定内容的文件(文本文件)
shell分为:
我们一般讨论shell都是指命令行shell。
bash之于shell就如同Ubuntu之于Linux。
linux内核相当于你的大脑。终端相当于你的眼睛。shell相当于可以将眼睛看到的多彩事物处理成大脑能接受的命令程序集。
Terminal(终端)是一个接受来自键盘输入,能够在窗口绘制文本的程序。实际上它是过去老式硬件终端的模拟。Terminal虽然能够接受来自键盘的输入,但是并不知道用这些输入来做什么。终端需要另一个程序来帮助它,这就是Shell。Shell将你的输入解释为命令,找到对应的程序来执行你的命令。并将执行的结果返回到Terminal。Shell也可以理解为你输入指令的默认执行者。程序员们在过去写了很多Shell程序,有BourneShell(sh)、CShell(csh)、KornShell(ksh)、ZShell(zsh)和BashShell。不同的操作系统默认安装的Shell不太一样。
希望题主明白,无论是编译执行还是解释执行,都是解释执行,只不过编译执行是用机器语言来解释。机器指令是在操作系统将编译后的程序加载进入内存之后,芯片电路进行解释的。而脚本语言则是在解释器将代码Parse(解析)之后,用编写解释器的语言来解释的,这中间多了一层,在效率上一般会低很多倍。即使是解释器,为了提高解释执行的效率,一般也会设计构建一个虚拟机,并在Parse的时候将源代码编译成字节码,然后对字节码逐条指令地执行。
这个作者提到了一个有趣的项目:c4
它简洁,却不简单。
ARuntimeEnviroment(likesaytheJavaRuntimeEnviroment)istheVMandasetofstandardruntimelibraries(java.utiletc).AJavascriptengine(likeV8)isaRuntimeEnviroment(soVMandthestandardlibraries)forJavascript.
实际上编程语境中的runtime大概有三个含义,分别指
你这么理解运行时就可以了:他是一个用来支持你写的程序的程序。
这是泛化的定义,因为不同语言的运行时非常的不同。复杂程度也不一样,比如Java的运行时要比cRust之类复杂很多。
比如,go的运行时就是一个调度程序加垃圾回收程序,编程时候写的goroutine和内存管理就是这个运行时程序负责实现的。
Python的运行时是一个c程序,里面包括垃圾回收,字节码解释器,反射等等功能…
Python为啥慢呢?
Python慢跟语法没有关系,原因在于上面三个。换句话说,慢的根源在于Python的运行时设计。不改变这个,翻译成啥都没用。
题外话,Python的这些设计换来的就是python的灵活度,程序员在写程序的时候几乎不需要考虑内存控制,类型等等。
举个简单的例子:int类型最简单的类型了,在C语言中(或者其他lowlevel语言中,比如Go)需要指明宽度和符号。比如int8,unsigned等等。不同的宽度的极限值也不一样,比如一个int8,只能表达-128to127这个区间的整数,超了程序就崩溃了。
在Python里面,int虽然也叫int,但是他可以表达任意大的整数。为啥呢?因为int在Python的世界里是一个特殊的对象,在内存里也不仅仅是几个字节那么简单,而是一个C的结构体:
ob_base={ob_base={ob_refcnt=8ob_type=0x00000001004936f0}ob_digit=([0]=30)如上,其实Python的int是一个array。。。然后每一个int都有这么一个结构在内存里。。当然比C的int复杂。但是好处也很明显,你不需要考虑什么int8int16,不用担心溢出。