我经常听到人们建议学习C.了解计算机性能,这是个好主意吗? 你确定 为了绝对清楚,我将立即概述本文的结论:
- C不是计算机的工作方式。
- 我认为大多数人都不会直接说出来,所以没关系。
- 了解上下文意味着,根据您的目标,出于这个原因学习C仍然有意义。
我计划再写两篇文章,对结论作更详细的解释,但这已经足够了。 文章发表后,请在此处添加链接。
我经常听到人们这样说:
通过学习C,您可以了解计算机的工作方式。
我不认为这个想法最初是错误的,但它有所保留。 如果您牢记这些,这可能是学习新事物和重要事物的可行策略。 但是,我很少看到有人详细讨论这些保留,因此,我写这篇文章是为了提供一个非常必要的上下文...如果您正在考虑学习C以了解计算机的工作原理,那么本文适合您。 希望她能帮助您解决。
在我们真正开始之前,我还要说一件事:如果您想学习C,那么请学习! 学习很棒。 学习C对于我对计算和我的职业的了解变得非常重要。 学习这种语言及其在编程语言历史中的地位将使您成为一名更好的程序员。 您不需要任何借口。 学习只是为了学习。 本文旨在作为了解真相的指南,而不讨论是否学习C。
首先,通常向谁推荐这个想法。 如果您试图“找出计算机的工作方式”,那么不用说您当前还不了解这一点。 哪些程序员不了解计算机如何工作? 我基本上看到这种感觉来自那些主要使用诸如Ruby,Python或JavaScript之类的动态类型“脚本”语言进行编程的人。 他们之所以说“不知道计算机如何工作”,是因为这些语言在虚拟机内部工作,而虚拟机只在其中起作用。 最后,虚拟机的整体思想是提供可移植性。 目标是不依赖于运行VM的设备。
只有一个问题:C
也可以在虚拟机中运行。
抽象机C
根据
规范C99的第5.1.2.3节“程序执行”:
本国际标准中的语义描述描述了与优化问题无关的抽象机器的行为。
我认为,这是学习C语言时最重要的事情。该语言不是“描述计算机的工作方式”,而是描述“抽象C机器”的工作方式。 其他所有重要的内容都源于这个概念。
还有一点需要注意:我选择的不是最新的C标准C99,为什么? 好吧, MSVC具有...有趣的C语言支持 ,这些天我是Windows用户。 是的,您可以在Windows上运行clang
和gcc
。 就我们在说什么,C89,C99和C11之间没有太大差异。 在某个时候,您必须选择。 我在这里提到的版本包括对原始规范的一些更改。
您可能在C谈话中听到了另一句话:“ C是便携式汇编程序。” 如果您仔细考虑一下这句话,您将会理解,如果这是真的,那么C就无法与计算机的运行相对应:有许多具有不同体系结构的不同计算机。 如果C像是在具有不同体系结构的不同计算机上运行的汇编程序,则它不能同时完全像这些计算机中的每一个一样运行。 他
必须隐藏细节,否则他将无法携带!
但是,我认为这一事实并不重要,因为人们几乎没有从字面上提及“ C是计算机的工作方式”。 在回到这一点之前,让我们讨论一下抽象的C机器,以及为什么许多人似乎不了解C的这一方面。
离题:人们为什么会误会?
我只能谈谈我的经历,尽管可以肯定的是,这并不是唯一的。
我学习了GW-BASIC,然后学习了C,然后学习了C ++,然后学习了Java。 在Java出现四年后的1999年,我开始编写Java之前就听说过Java。 当时的市场营销积极地将Java和C ++进行了对比,它以JVM作为平台为重点,并以机器模型将其与C ++区别开来,因此C. Sun Microsystems不再存在,但
新闻发布镜面提醒我们:
Java应用程序是独立于平台的。 您只需要将Java虚拟机移植到每个平台即可。 它充当用户计算机和Java应用程序之间的解释器。 用Java环境编写的应用程序可以在任何地方工作,而无需将应用程序移植到多个平台。
主要座右铭是“写一次,到处跑”。 这两个句子成为了我(以及其他许多人)理解Java的方式,以及它与C ++的不同之处。 Java具有解释器,即Java虚拟机。 C ++中没有虚拟机。
通过如此强大的营销,许多人心目中的“虚拟机”已成为“大型运行时和/或解释器”的代名词。 没有此功能的语言与特定的计算机过于捆绑,因此需要移植,因为它们并不是真正的平台独立。 Java存在的主要原因是此C ++缺陷的更改。
对于同一基本概念,“运行时环境”,“虚拟机”和“抽象机”是不同的词。 但是从那以后,由于这些想法的实现略有差异,他们收到了不同的含义。
我个人认为1995年的营销是程序员仍然误解C的本质的原因。
那么这句话是假的吗? 为什么Sun Microsystems会花费数百万美元来促进谎言? 如果C也是基于提供跨平台可移植性的抽象机,那么为什么需要Java? 我认为这是理解人们说“ C是计算机的工作原理”时真正含义的关键。
人们到底是什么意思?
尽管C在虚拟机的上下文中工作,但它仍然与类似Java的语言有很大的不同。 太阳没有说谎。 要了解,您需要了解S.的故事
1969年,贝尔实验室用汇编语言编写了一个计算机操作系统。 1970年,它被称为UNIX。 随着时间的流逝,贝尔实验室购买了越来越多的新计算机,包括PDP-11。
当需要将Unix移植到PDP-11时,他们决定使用高级语言,这在当时是一个非常激进的想法。 想象一下,今天我将告诉您:“我将用Java编写OS” –尽管这个
想法是可以实现的 ,但您可能会大笑。 情况(据我所知,当时我还没住)。 我们考虑了一种叫做B的语言,但是它不支持PDP-11所具有的某些功能,因此他们将其称为“ C”来创建后继,因为它是字母表中的下一个字母。
没有语言“ A”。 B继承了BCPL(基本组合编程语言)。
1972年,第一个C编译器是在PDP-11上编写的,同时将UNIX重写为C。最初,他们没有考虑可移植性,但是C赢得了名声,因此C编译器被移植到其他系统。
1978年,《编程语言C》一书的第一版出版。 根据其作者的名字,它被人深情地称为“ K&R”,与本书的规范完全不同,但同时又详细描述了该语言,因此其他人也尝试编写编译器C。后来,该“版本”将称为“ K&R C”。
随着UNIX和C的普及,它们都被移植到许多计算机上。 在70年代和80年代,他们的硬件基础在不断增长。 由于B不支持PDP-11的所有功能,因此创建C的方式与创建C的方式相同,许多编译器都使用语言扩展。 由于只有K&R而没有规范,因此只要扩展相当接近,就可以认为这是可以接受的。 到1983年,缺少任何标准化都导致了问题,因此ANSI成立了一个小组来准备该规范。 1989年,C89标准问世,有时也称为“ ANSI C”。
规范C试图统一各种硬件上的这些不同实现。 因此,抽象的C机器是一种最小的规范,它允许相同的代码在所有平台上都可以相同地工作。 C实现是编译的,没有解释的,因此没有解释器,因此从1995年开始就没有“ VM”。 但是,C程序是在不存在的抽象计算机上编写的,然后将代码转换为特定于运行该程序的特定计算机的汇编程序。 您不能依靠某些特定的细节来编写可移植的C代码,这使编写可移植的C变得非常困难,因为在编写代码的初始版本时可能已经做出了特定于平台的假设。
一个例子可以最好地说明这一点。 C中的主要数据类型之一是
char
,来自单词“ character”。 但是,抽象C机器无法确定
char
应包含多少位。 好吧,可以确定,但不能确定数量。 它确定
CHAR_BIT
的大小,这是一个常数。 规范的第5.2.4.2.1节:
下面给出的值应替换为预处理指令#if
使用或使用的常数表达式。...在特定实现中,值的大小(绝对值)应等于或大于此处带有相同符号的值。
CHAR_BIT: 8
换句话说,您知道
char
至少为8位,但是实现可能更大。 为了正确地编码“抽象C机”,在处理
char
时必须使用
CHAR_BIT
而不是
8
。 但是,这并不是我们认为的虚拟机的某种解释器功能。 这是编译器如何将源代码转换为机器代码的属性。
是的, 有些系统的 CHAR_BIT
不是8
。
因此,尽管在技术上与Java虚拟机具有相同的思想,但这种“抽象机”更可能是用于在创建汇编代码时管理编译器的编译结构,而不是某种运行时检查或属性。 Java中的等效类型是
byte
,始终为8位,并且JVM实现的任务是在具有更多字节的平台上执行操作。 (不确定JVM是否可以在这些平台中的任何一个上运行,但这就是它的工作方式。) 抽象的C机器是作为各种“硬件”的最小包装而创建的,而不是作为用软件为您的代码编写的某种由坚固的织物制成的平台而创建的。
因此,尽管Sun在技术上是错误的,但实际上,它们的
含义只是字面意义上的一点,而它们的
含义是正确的。 短语“学习C以了解计算机的工作原理”也是一样。
学习C更好地了解计算机的工作方式
人们到底
是什么意思? 在“摩擦主义者应该学习C以了解计算机如何工作”的上下文中–这是一条建议,建议“降到铁的水平”。 也就是说,不仅要了解您自己的程序在虚拟机内部的工作方式,而且要了解程序和VM的组合如何在虚拟机本身的上下文中工作。
学习C
将为您提供更多这些细节,因为抽象机更接近硬件以及操作系统的抽象。 C语言与高级语言有很大的不同,因此学习它可以教很多东西。
但是请务必记住,C本质上是硬件
抽象 ,并且抽象是不完美的。 小心C做什么或它如何与机器本身一起工作。 如果您做得太深,您肯定会遇到这些差异,这可能会引起问题。 大多数针对C的培训资源,尤其是在当今设备越来越同类的今天,将提倡计算机就是
这样工作的。 因此,学生可能很难理解引擎盖下正在发生的事情以及C提供的抽象概念。
在讨论中,我们甚至没有涉及其他问题。 例如,由于C的广泛普及,硬件趋向于抽象C机器的语义,从而使硬件变得更加统一;如果您的体系结构与C语义的差异太大,则C程序的运行速度可能会慢于其他程序。并且硬件速度通常通过C语言中的测试来衡量。本文已经相当长了...
出于这个原因,我认为此陈述的更准确的说法是“通过学习C,您
将学到
更多有关计算机工作原理的信息。” 我真的认为,对C的熟悉对许多程序员都是有用的,即使他们自己不编写C。引入C也可以使您了解我们的行业历史。
还有其他方法可以探索该主题。 C
本质上不是为研究计算机而设计的,但这是一个不错的选择。
在编程方面有很多东西要学习。 祝您旅途顺利。