目前,C被认为是一种低级语言,但是早在70年代,它就被认为是低级语言吗?那这个词甚至还在使用吗?

直到80年代中期及以后,许多流行的高级语言才出现。

评论

作为一个数据点,大约在1978年,一些编程指导员向我描述了C作为一种赞美的汇编语言。

@BenCrowell我不确定在您的声明中“荣耀”是什么意思,但是我曾经历过将C称为通用(独立于平台)的汇编语言。
有趣的是,有一种情况认为C不是一种低级语言,并且现在比70年代还少。这是因为C的抽象机与PDP-11相比,从现代硬件中移出的距离更远。 br />
考虑到这一点,您可能还想考虑起源-Unix是用C编写的,c在Unix上运行,并将unix交叉编译到其他平台。编译Unix不需要做的任何事情都是不必要的开销,C的主要目标是使编写/移植编译器变得尽可能容易。为此,它是EXACT正确的级别,因此我不认为C是高级别还是低级别,我认为它是移植Unix的工具,就像几乎所有Unix工具一样,它非常适应许多问题。 br />
值得注意的是,lisp于1958年发明了

#1 楼

要回答这个问题的历史方面:

Brian Kernighan和C设计师Dennis Ritchie编写的C编程语言(您可能听说过的“ K&R”)解释了设计哲学。第一版的序言说


C不是一种“非常高级”的语言,也不是一种“大”的语言...


并且引言说


C是一种相对“低级”的语言... C没有提供直接处理诸如字符串,集合,列表或数组之类的复合对象的操作。没有操作可以操纵整个数组或字符串的操作...


在文本继续之前,该列表会持续一段时间:


尽管缺少其中一些功能似乎是严重的缺陷,但是……将语言缩小到适中的大小会有真正的好处。


(我只有1988年的第二版,但是下面的注释表明所引用的文本与1978年第一版中的内容相同。) C被设计为介于两者之间。可以用C语言编写可跨硬件平台移植的代码,这是当时是否将该语言视为高级语言的主要标准。但是,C缺少一些高级语言所特有的功能,这是一个设计的决定,它简化了。

评论


这是一个很好的答案!可操作的历史证据+演员的证词,在《任择议定书》所指的时期内能最好地了解低和高水平的含义。顺便说一句,我确认这些报价已经在1978年版中了。

–克里斯托弗(Christophe)
18年7月1日在16:42



#2 楼

这取决于您对高级和低级语言的定义。在开发C时,任何比汇编语言都高级的语言都被视为高级语言。这是一个需要清除的低门槛。后来,这个术语转移到了如今有些人甚至将Java都视为低级语言的地步。

即使在70年代的高级语言环境中,也值得指出的是C是相当低的水平。 C语言基本上是B加一个简单的类型系统,并且B仅仅是一个方便的用于汇编的过程/结构化语法层。由于类型系统是对无类型B语言的改型,因此您仍然可以在某些地方省略类型注释,并使用int。当时已经很完善的功能,例如


自动内存管理基本的OOP或协程
更具表现力类型系统(例如,范围受限的类型,用户定义的类型,例如记录类型,强类型等等)



支持递归(由于与所有变量都具有全局生存期的语言相比,基于堆栈的自动变量的结果)
函数指针
不久之后实现了用户定义的数据类型(结构和联合) C的初始版本。
C的字符串表示形式(指针到字符)实际上是对B的巨大改进,B将多个字母编码成一个mac隐词。
C的头文件是一个高效的技巧,可以使编译单元保持较小的大小,但同时也提供了一个简单的模块系统。指针本质上是不安全的,但是对于底层编程也非常有用。

在开发C的时候,其他创新语言,例如COBOL,Lisp,ALGOL(各种方言),PL / I,SNOBL,Simula和Pascal已被发布和/或广泛用于特定的问题领域。但是,这些现有的语言中大多数都是用于大型机编程的,或者是学术研究项目。例如。当ALGOL-60最初被设计为通用编程语言时,实现它的必要技术和计算机科学还不存在。其中一些(某些ALGOL方言,PL / I,Pascal)也旨在用于低级编程,但它们往往具有更复杂的编译器或过于安全(例如,没有无限制的指针)。 Pascal显然缺乏对可变长度数组的良好支持。 C从来不是一个主要的语言设计研究项目。相反,它是在资源有限的PDP-11小型计算机上Unix内核开发的分支。对于它的利基市场(使用易于移植的单通编译器编写Unix的极简主义低级语言),C绝对出色–超过45年后,它仍然是系统编程的通用语言。

评论


对于不了解现有ALGOL家族和Pascal语言需要什么的人来说,这只是一小部分:这些语言具有词法嵌套的函数,您可以在其中访问外部函数中声明的(局部)变量。这意味着要么必须在每个函数调用和返回(更改了词法级别)时维护“显示”(指向外部词法作用域的指针数组),要么必须将词法作用域链接到堆栈以及每个此类变量访问需要在堆栈上进行多次间接跳转才能找到它。昂贵! C抛弃了所有这些。我仍然想念它。

– davidbak
18年7月1日在5:42

@davidbak:x86-64系统V ABI(又称Linux / OS X上的调用约定)将%r10定义为“静态链指针”,这正是您在说的。对于C来说,这只是另一个调用过多的暂存器,但我想Pascal会使用它。 (当此类函数未内联时,GNU C嵌套函数将其用于将指针传递给外部范围(例如,如果您创建指向该函数的指针,以便编译器在堆栈上创建机器代码的蹦床):常规的可接受性r10和r11的用法)

– Peter Cordes
18年7月1日在8:54



@PeterCordes着迷!当System V发布时,Pascal仍被广泛使用(尽管我不知道何时定义正式的SysV ABI)。您的链接答案非常有用。

– davidbak
18年7月1日在16:03



C具有用户定义的类型(结构/联合)。我怀疑其余的这些“功能”被忽略了,因为它们的使用为零或否定(除非您参加混淆的代码竞赛:-),因为它们不利于保持语言既简单又富有表现力的目标。

–jamesqf
18年7月1日在17:25

@jamesqf:但是很早的C就没有结构分配;我想您必须单独进行成员复制或复制,而不要编写a = b;以您可以在ISO C89中复制整个结构的方式进行复制。因此,在早期的C语言中,用户定义的类型绝对是第二类,只能通过引用作为函数args传递。 C对数组的厌恶,以及为什么C ++支持在结构中对数组进行成员分配,但通常不支持?

– Peter Cordes
18年7月1日在22:17

#3 楼

在1970年代初期,使用现代结构使C充满了新鲜的空气,以至于整个UNIX系统都可以从汇编语言重写为C,而空间或性能的损失却微不足道。当时,许多同时代人都将其称为高级语言。不是一种非常高级的语言。“
丹尼斯·里奇(Dennis Ritchie)带着挑剔的笑容,想要挑衅,会说这是一种低级语言。他对C的设计目标中的首要目标是使语言与机器保持紧密联系,同时又提供可移植性,即机器独立性。

有关更多信息,请参阅BSTJ原始文章:谢谢丹尼斯。愿你安息。

评论


如果您问我,它基本上是PDP组装的类型和语法更好的包装器。

– einpoklum
18年6月30日在22:43

@R .. ... 68000机器语言本身支持C构造,部分是由于PDP-11与68000计算之间的相似性!杂志1986年7月。

–基督
18年7月1日在5:12

@einpoklum我倾向于同意这一点。大约在1980年,我在大学时就通过PDP-11 / 34a学习了C语言,并且一位教授将其描述为“便携式汇编语言”。可能是因为除了PDP-11之外,我们在实验室中还拥有几台Superbrain CP / M机器,这些机器上都提供了C编译器。 zh.wikipedia.org/wiki/Intertec_Superbrain

– dgnuff
18年7月1日在8:09

基于可验证的历史证据,这也是一个很好的答案(哇!那里有K&R的预版本!)。

–克里斯托弗(Christophe)
18年7月1日在16:47

@einpoklum这有点牵强吗?我有机会在80年代中期用汇编器(Z80和M68K),一个称为M(带有抽象的16位寄存器和指令集的PDP11语法)和C的“便携式汇编器”和C编写系统和应用程序代码。 ,C绝对是高级语言:C编程的效率比汇编程序高出一个数量级!当然没有字符串(SNOBOL),没有本机数据文件支持(COBOL),没有自生成代码(LISP),没有高级数学(APL),没有对象(SIMULA),因此我们可以同意它不是很高

–克里斯托弗(Christophe)
18年7月1日在17:02

#4 楼

正如我在该站点上的其他地方所写的,当有人将malloc / free内存管理模式称为“低级编程”时,


时间。当我第一次学习编程时,任何提供标准化堆模型(使简单的分配/释放模式成为可能)的语言都被认为是高级的。在低级编程中,您必须自己跟踪内存(不是分配,而是内存位置本身!),或者如果您真的很喜欢,请编写自己的堆分配器。


在上下文中,这是在90年代初期,即C语言问世之后。

评论


自80年代末标准化以来(不是基于现有的Unix API),标准库不是唯一的东西吗?同样,内核编程(这是C的原始问题域)自然需要诸如手动内存管理之类的低级内容。当时,C一定是编写严肃内核的最高级别的编程语言(我认为如今NT内核也使用了大量的C ++)。

–阿蒙
18年6月30日在16:36

@hyde,我使用了Algol 60,两种不同的FORTRAN方言以及1970年代的几种不同的BASIC方言,这些语言都没有指针或堆分配器。

–所罗门慢
18年6月30日在23:49



严格来说,您仍然可以通过直接调用brk(2)或mmap(2)并自行管理结果内存而无需malloc()进行编程。这是一个巨大的PITA,没有任何可想像的好处(除非您碰巧正在实现类似malloc的操作),但是您可以做到。

–凯文
18年7月1日在3:45



@amon-除了出色的基于Burroughs堆栈的计算机,这些计算机是在ALGOL中从下到上编程的,而且比Unix早得多。哦,顺便说一下,Multics,它是Unix的灵感:用PL / I编写。与ALGOL类似,比C高。

– davidbak
18年7月1日在5:51



实际上,今天我们更多人不使用Multics的原因可能与它仅在非常昂贵的大型机上运行有关,即,当日典型的大型主机费用加上半个机柜的额外费用专用硬件以实现具有安全性的虚拟内存。当像VAX-11这样的32位小型计算机问世时,除了银行和政府之外,所有人都从IBM和七个小矮人中撤出,并将其大规模处理转移到“小型”计算机上。

– davidbak
18年7月1日在22:37



#5 楼

许多答案已经提到了早期的文章,这些文章说“ C不是高级语言”之类的东西。时间-Algol,Algol-60,PL / 1,Pascal-提供了数组边界检查和数字溢出检测。

最后我检查了缓冲区,整数溢出是许多安全漏洞的根本原因。 ...是的,情况仍然如此。 >
因此,如果您对HLL的定义包括“自动防止许多低级错误”,那么,如果没有发生C和UNIX,网络安全的遗憾状态将大为不同,甚至可能更好。

评论


由于我碰巧参与了Intel MPX的实现以及是否编译出了指针/边界检查编译器,因此我可以向您介绍有关其性能的论文:本质上为5-15%。其中大部分涉及到在1970年代和1980年代几乎不可能进行的编译器分析-与天真的检查相比可能要慢50%。但是,我认为可以说C和UNIX在20年之前就推迟了此类分析工作-当C成为最流行的编程语言时,对安全性的需求就少得多。

– Krazy Glew
18年7月1日在17:45

@jamesqf此外,C之前的许多机器都对边界检查和整数溢出有特殊的硬件支持。由于C没有使用该硬件,因此最终将其弃用并删除。

– Krazy Glew
18年7月1日在17:48

@jamesqf例如:MIPS RISC ISA最初基于斯坦福基准测试,该基准最初是用Pascal编写的,后来才移至C。由于Pascal检查有符号整数溢出,因此MIPS在ADD等指令中也进行了检查。大约在2010年,我在MIPS工作,我的老板想删除MIPSr6中未使用的指令,研究表明,几乎从未使用过溢出检查。但事实证明Javascript进行了此类检查-但由于缺乏操作系统支持而无法使用便宜的指令。

– Krazy Glew
18年7月1日在17:56

@KrazyGlew-您提出来这很有趣,因为在C / C ++中,由于有符号整数溢出,用户和编译器作者之间针对“未定义行为”的争执正在升温,因为今天的编译器作者秉承了古老的口头禅“制造错误程序变坏是没有罪”,并将其提高到11。大量关于stackoverflow和其他地方的帖子反映了这一点...

– davidbak
18年7月1日在22:45



如果Rust具有像C这样的SIMD内在函数,它可能是近乎理想的现代便携式汇编语言。由于基于UB的积极优化,以及无法移植暴露现代CPU支持的新原始操作(例如popcnt,计数前导/尾随零,位反转,字节反转,饱和),C作为一种便携式汇编语言变得越来越糟数学)。要使C编译器在具有硬件支持的CPU上为它们进行高效的汇编,通常需要不可移植的内在函数。让编译器在没有目标的情况下在目标上模拟popcnt胜于获得popcnt的成语识别。

– Peter Cordes
18年7月1日在22:59

#6 楼

考虑一下早于C(1972)的语言,它的出现时间更长,更高级:

Fortran-1957年(不比C高很多)

Lisp-1958年

> Cobol-1959年

Fortran IV-1961年(不比C高很多)

PL / 1-1964年

APL-1966年
/>
再加上RPG(1959)这样的中级语言,主要是一种编程语言,以取代基于插件的单位记录系统。仅比当时大型机上使用的宏汇编程序高一点。对于IBM大型机,由于当时尚未将数据库接口移植到Cobol,导致将汇编程序宏用于BDAM(基本磁盘访问方法)之类的数据库访问,从而导致组合和今天,IBM大型机上仍在使用Cobol程序。

评论


如果要列出较旧的较高语言,请不要忘记LISP。

–重复数据删除器
18年7月2日在21:53

@Deduplicator-我将其添加到列表中。我一直专注于在IBM大型机上使用的软件,我不记得LISP这么流行,但是APL还是IBM大型机(通过分时控制台)和IBM 1130的利基语言。例如,使用更独特的高级语言查看使用当前APL版本创建Conway的生活游戏所需的代码很少:youtube.com/watch?v = a9xAKttWgP4。

–rcgldr
18年7月3日在8:00



我不会把RPG或COBOL视为特别高级,至少在COBOL-85之前是这样。刮擦COBOL的表面时,您会发现它本质上是非常高级的汇编程序宏的集合。首先,它缺少功能,过程和递归,以及任何形式的作用域。必须在程序的顶部声明所有存储,否则将导致极其长的序曲或痛苦的变量重用。

– idrougge
18年7月3日在11:25

我对使用Fortran IV有一些不好的回忆,我不记得它比C明显“更高”。

– DaveG
18年7月3日在13:54

@idrougge-COBOL和RPG,以及大型机指令集包括对打包或未打包BCD的完全支持,这是美国等国家/地区对财务软件的要求。我认为诸如“移动对应”之类的相关本机运算符是高级的。 RPG与众不同之处在于,您指定了原始输入字段与格式化输出字段和/或累加器之间的链接,但没有指定操作顺序,与其替换的插件编程类似。

–rcgldr
18年7月3日在20:53

#7 楼

问题的答案取决于询问的C语言。

Dennis Ritchie的1974 C Reference Manual中描述的语言是一种低级语言,它为高级编程提供了一些便利。语言。从该语言衍生的方言同样也倾向于是低级编程语言。

当1989/1990 C标准发布时,它并没有描述已成为编程流行的低级语言。真正的机器,而是描述了可以(但不是必须)以较低级别的术语实现的较高级别的语言。

作为C Standard的作者,使该语言有用的原因是许多实现可以被视为高级汇编器。由于C还被用作其他高级语言的替代,并且由于许多应用程序不需要执行高级语言无法完成的功能,因此该标准的作者允许实现以任意方式运行如果程序尝试使用低级构造。因此,C标准描述的语言从来都不是低级编程语言。

要了解这种区别,请考虑Ritchie的Language和C89如何查看代码片段:

在“ char”为8位,“ int”为16位big-endian,
“ float”为32位且结构没有特殊填充或对齐
的要求,因此“ struct foo”的大小为8个字节。加3 * 8 + 2 [即26]个字节,然后从该地址处的字节和下一个字节中提取
16位值,在该值上添加一个
,然后将该16位值写回相同的两个
字节。该行为将定义为对26号和27号进行操作
字节p,位于地址p后面的字节,而不考虑存储在其中的
对象的类型。 “ struct foo []”的元素,然后是至少三个以上该类型的complete元素,最后一条语句将在* p之后的第三个元素的member
在任何其他情况下,行为都不会由标准来定义。和结构(方便)时,它根据内存中对象的基本布局定义了行为。相比之下,C89和更高版本的标准所描述的语言是根据更高级别的抽象来定义事物的,只有
才能定义与之一致的代码行为。适用于低级编程的高质量实现在比标准规定的情况更多的情况下将发挥更大的作用,但是没有“官方”文档指定必须执行何种操作才能适合此类目的。

因此,丹尼斯·里奇(Dennis Ritchie)发明的一种语言是一种低级语言,因此被认为是低级语言。但是,在缺乏实施提供的超出标准职责范围的保证的情况下,C标准委员会发明的语言从来都不是低级语言。

评论


这似乎说同一语言既是高级语言又是低级语言,具体取决于文档中所说的内容。

–user253751
20年11月5日,9:16

@ user253751:我想人们是否使用术语“高级”和“低级”来描述语言的种类或种类。 Sorta很喜欢男中音是会唱歌高音的低音,还是会不会高音的男高音的问题。

–超级猫
20/11/15在15:39