从C中学到了哪些高级语言无法学习的原理?[关闭]


11

我相信C是学习编程背后原理的好语言。对于那些与高级语言(如Ruby)“相去甚远”的低级语言,您打算学什么?


2
无论如何,您都可以学习魔术或其中的一些。由于C是“更接近金属”,因此您将了解有关金属的更多信息。
罗伯特·哈维

1
在遇到C ++之前,我从未完全理解引用的概念。
user6245072

6
C会教你什么实际上是堆栈溢出。艰难的方式。
david25272 '16

1
我希望新的程序员将从学习良好的旧Pascal和结构化编程开始。您将学习逻辑表达和结构化表达。
弯曲

2
只有C和C ++可以教给您的是编译器是您最大的敌人。
CodesInChaos

Answers:


9

在计算机科学的一般抽象意义上,没有C语言中存在的,高级语言中也没有的原理。所有计算机科学都归结为算法,并且所有算法都可以用C一样具有图灵完备性的任何语言来实现。

C携带高级语言的区别类似于机器代码与C区别的区别:机器与代码的关系。

用高级语言编写代码时,您(通常)不必担心代码与计算机的交互方式。语言为自己定义的虚拟机隐藏了代码执行的许多方面。

在C语言中,程序与内存的交互始终处于最前沿。不仅仅是要管理堆的使用,还包括代码与堆栈的交互,以及代码对内存的访问如何影响代码的行为和性能,甚至不影响内存访问的顺序。可以避免引起您的注意,因为在错误的时间读取错误的内存可能会严重削弱性能。

在高级语言中,这些事情根本不那么明显。内存是在您不知情的情况下分配和释放的,有时是在您不提示的情况下进行的。通常,这完全是您无法控制的。大多数内存分配的时间,地点,方式和原因都对您完全隐藏了。

同样,从另一个方向看,编写机器代码或汇编代码将更多细节带到了前台:几乎没有什么东西不在您的权限范围之外,并且必须在编写代码时了解传递的每个分配,每个资源,每个数据段。通过CPU的寄存器-到目前为止,这些知识已从高级语言中删除,从而变得晦涩难懂。


6
我从不完全理解为什么人们总是在这类讨论中提到图灵完备性。图灵完整性在这种情况下没有意义。在这方面,C与其他编程语言没有什么不同,因此通过切换到C对图灵完备性没有任何了解。图灵完备性唯一有意义的时间是在讨论诸如CSS或HTML之类的图灵完备性的事物时。地狱,如果您斜视一下就足够了,即使那些都已经完成了图灵。更有意义的问题集中在可用性上。
罗伯特·哈维

3
@RobertHarvey我的观点是,只要一种语言具有合理的最低计算能力,从算法的角度来看,它的“级别”就变得无关紧要,这是在这种情况下唯一重要的事情。
greyfade

3
因为您要提出的观点与OP的问题完全无关紧要。程序员一直在这样做;他们扔掉了“ Turing-complete”一词,因为它实际上在实践上有一些有意义的用法。没关系
罗伯特·哈维

2
<讽刺>生物学只是化学的特例,粒子物理学的特例。如果您了解粒子物理学,那么您将无法从生物学中学到任何东西。是吗?</ irony>
Florian F

3
值得指出的是,C只是要求您明确分配和释放,但它们仍与抽象机器有关,就像在“高级”语言中一样-物理(例如)x86机器仍然不在C的范围内。可以制作出完美的沙盒VM,该VM可以解释C代码,但无法控制物理机的内存分配,并且仍然可以实现100%的一致性。
Theodoros Chatzigiannakis

13

我知道C是学习编程背后原理的好语言。

我不同意。C缺少太多功能,无法学习编程背后的原理。C创建抽象的功能很糟糕,抽象是编程背后的关键原理之一。

如果您想了解硬件的工作原理,从而对机器有所机械同情,则应该学习机器代码(又称指令集架构),并研究现代CPU的缓存结构。请注意,我不建议使用汇编语言,只需了解硬件说明,即可了解编译器生成的内容。

如果您想学习编程原理,请使用Java,C#或Swift等现代语言,或使用Rust等数十种其他语言之一。另外,研究各种编程范例,包括函数式。


12
C擅长创建抽象。您可以编写方法C,你可以打包数据结构C.全部操作系统使用C.什么C已建成并不擅长的是满足什么面向对象是每个人的“现代”的想法应该看喜欢。
罗伯特·哈维

4
不完全的。C比ASM高很多。只是不要期望在其中使用类,尽管如果您愿意,可以使用多种方法
罗伯特·哈维

4
在您的注释中将“ Brainfuck”替换为“ assembler”,它仍然适用。但这并不意味着我很快就会使用Brainfuck。
罗伯特·哈维

6
仅当您认为类(和垃圾回收等)是教导新程序员的必要元素时(我不是),您对C功能的争论才真正有价值。这里没有人提倡尝试以无类语言使用类。
罗伯特·哈维

5
@Robert,我的论点是C是一种较低级的语言,因此它几乎不是理解编程原理的最佳语言,我们也可以说汇编语言,仅仅因为它们是较低级的语言并不意味着它们在某种程度上更接近于“真正的”编程原理。这些语言更好地理解了硬件和操作系统的工作方式,如果有兴趣,我建议在学习指令集体系结构和机器语言时直接跳到最低级别。否则,有很多语言可供选择。
埃里克·艾德

8

C和(抽象)机

大多数编程语言都是用抽象机来描述的。然后,使用诸如编译器,链接器,汇编器,解释器,静态分析器,中间语言和硬件之类的工具集来实现这些工具这些工具将共同产生至少尊重抽象机所有预期行为的结果,如程序所观察到的那样。

C并非以上规则的例外。它是根据抽象机器进行描述的,该抽象机器不了解您的实际硬件。

因此,当人们说C教您计算机的实际工作原理时,通常意味着C教您C的工作原理。但是C在系统编程中如此普及,可以理解很多人开始将C与计算机本身混淆。我个人甚至会说,了解C的工作方式通常比了解计算机本身的工作方式更为重要。

但是,C和计算机不同的东西。实际的硬件实际上很复杂-以某种方式使C规范像儿童读物一样读。如果您对硬件的工作方式感兴趣,则可以随时查阅手册并开始在汇编器中编写代码。或者,您总是可以开始学习数字电路,以便可以自己设计一些硬件。(至少,您将欣赏高级C的知识。)

如何你学到了什么?以及如何学到了什么?

好的,关于硬件的实际学习涉及C以外的事情。但是C可以今天向程序员教其他吗?

我认为这取决于。

  • 有些人会说,通过在提供和鼓励它的环境中工作常常可以通过多种方式更好地学习一个概念
  • 有些人会说,您可以通过在没有概念的环境中工作来更好地学习概念,而必须在该环境中自行构建。

选择这些可能性中的一种不要太快。我已经写了很多年的代码,但我仍然不知道哪个是正确的答案,或者正确的答案是否只是两个答案之一,或者在这个问题上是否有一个正确的答案。

我有点倾向于您可能应该最终按照我描述的顺序宽松地应用这两个选项。但是我不认为这确实是一个技术问题,我认为这是一个很有教育意义的问题。每个人似乎都以截然不同的方式学习。

独家C

如果您通过至少涉及我建议的第二个选项来回答上述问题,那么您已经有了一些答案:可以通过用C或C语言重新发明来更好地学习用高级语言学习的任何东西。最小扩展通过将C添加到混合中。

但是,不管您的回答是什么,您肯定都可以从C语言(甚至可能是其他几种语言)中学到一些东西。

  • C在历史上很重要。这是一个里程碑,您可以查看并了解我们的来历,也许还可以了解我们要去的方向。您可以理解为什么存在某些限制,并且可以理解某些限制已经解除。

  • C可以教您在不安全的环境中工作。换句话说,当某种语言(任何一种语言)由于某种原因不能为您或不会为您做时,它可以训练您注意自己。即使您在安全的环境中,这也可以使您成为更好的程序员,因为您自己产生的错误更少,并且您可以暂时关闭安全性,从而从其他安全的程序中挤出一些额外的速度(例如,使用指针)在C#中),在这种情况下,安全性会带来运行时成本。

  • C可以告诉您每个对象都有存储要求,内存布局,可以通过有限的地址空间访问内存的事实,等等。尽管其他语言不需要您关注这些问题,但在某些情况下,某些直觉可以帮助您做出更明智的决策。

  • C可以通过其构建系统教您链接和目标文件以及其他复杂性的详细信息。这可以使您对本机编译程序通常从源代码到执行如何进行有实际的了解。

  • C可以通过未定义的行为的概念使您的思维转向新颖的思维方式。在软件开发中,未定义行为是我最喜欢的概念之一,因为对非经典编译器的影响的研究是一种独特的思维方式,您无法从其他语言中完全理解。但是,您必须拒绝反复试验,并开始以认真和慎重的方式研究语言,然后才能完全理解此方面。

  • 但是作为一种小语言,C可以授予您的最重要的认识可能是所有编程都归结为数据和操作的想法。您可能希望将其视为具有层次结构的模块类和具有虚拟调度的接口,或使用纯数学函数进行操作的优雅的不可变值。一切都很好-但是C会提醒您这仅仅是数据+操作。这是一种有用的心态,因为它使您可以消除很多心理障碍。


5

C之所以对学习有好处,并不是因为它教了任何原理。它教你事物如何运作

可以将C与70或80年代的那些好老车之一进行比较,它们只是为了驾驶而设计的。您可以将它们拆开,拧紧,并了解每个部分的工作方式,以及它们如何与您可以拿到手中的其他部分一起工作。一旦了解了所有部分,便可以清楚地了解整个过程。

现代语言更像是一辆现代汽车,其引擎基本上是一个黑匣子,太复杂了,普通车主无法理解。那些车可以做很多事情,在这些日子里,他们正在积极学习自己驾驶。由于具有这种复杂性和舒适性,用户界面已经远离引擎实际发生的变化。

当您学习用C语言编程时,您会接触到许多计算机组成的螺钉和螺母。这使您可以了解机器本身。例如,它使您能够理解为什么构建这样的长字符串不是一个好主意:

java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
     result = result + components[i];
};

(我希望这是正确的Java,我已经有一段时间没有使用它了……)从此代码示例中,循环为什么具有二次复杂度并不明显。但是事实就是如此,这就是当您要连接数百万个小型组件时,此代码会停顿下来的原因。经验丰富的C程序员可以立即知道问题出在哪里,并且很可能一开始就避免编写此类代码。


我完全同意。C将教您很多事情的工作原理,这将有助于您理解a)编写高级语言的原因(例如,抽象出来的含义),以及b)这些高级语言在幕后的工作方式,肯定会拥有丰富的知识。它不会讲授原理,而且可能不那么容易,但是您会尊重它,使用计算机,从而对高级语言有更深的了解。另请参阅Joel Spolsky的《回到基础》:joelonsoftware.com/articles/fog0000000319.html
jleach,2016年

1
您的回答肯定很好,但是如果您for(int i = 0; i < strlen(s); i++)使用C 编写,则循环也将具有二次复杂度,并且与Java示例中的代码一样显而易见;-)
Doc Brown

不确定,但是我相信Java编译器可以优化这一点:-)
BrunoSchäpper16年

经验丰富的Java程序员还立即知道问题出在哪里,并且很可能一开始就避免编写此类代码。基本的Java教程中讨论了此特定问题。因此,这当然不是可以从C中学到的东西,而不能从Java中学到。
彼得·泰勒

@PeterTaylor如果您有一位知道C语言的Java老师,那么可以。但是我怀疑一旦知道C的人死了,这种知识是否会存在。对于C程序员来说,正是C字符串的定义,告诉他们我的代码示例效率不高。对于Java程序员来说,他们对所用抽象的知识有些深刻,晦涩难懂且很少使用,这可以告诉他们避免使用这种代码。好的,我在这里有点夸张,但是您明白了:C程序员必须知道这一点,Java程序员可能会不了解它而逃脱。
cmaster-恢复莫妮卡

2

有比C语言更好的语言来学习“编程背后的原理”,尤其是理论原理,但是C语言对于学习有关工艺的一些实用,重要的东西可能是一件好事。greyfade的回答肯定是正确的,但是恕我直言,与您自己管理内存相比,您可以从C中学习更多的知识。例如,

  • 在没有异常的情况下如何创建具有完整错误处理的程序

  • 如何在程序中创建结构而无需任何面向对象的语言支持

  • 如何在缺少数据结构(如动态可伸缩列表,字典或有用的字符串抽象)的情况下处理数据

  • 即使编译器或运行时环境未自动警告您,如何避免常见错误(如数组溢出)

  • 如何创建通用解决方案,而无需模板或通用语言的支持

  • 我是否提到过您可以学习如何自己管理内存?;-)

此外,通过学习C,您将了解C ++,Java,C#,Objective C的语法通用性从何而来。

在2005年,Joel Spolsky撰写有关学习C 的建议建议先学习其他高级语言。他的论据是

  • “您将永远无法使用高级语言创建高效的代码。”

  • “您将永远无法在编译器和操作系统上工作,这是周围最好的编程工作。”

  • “您永远不会被信任为大型项目创建架构”

  • “如果您无法解释为什么while(*s++ = *t++);复制字符串,或者如果这不是世界上最自然的东西,那么,您是基于迷信进行编程的

当然,他的著作无疑是有争议的,但是恕我直言,他的许多论点在今天仍然有效。


1
在学习“您认为C不支持的高级事物”之前,C是一种非常好的语言,因为它可以帮助您了解这些事物的实际工作方式(以及它们的价格如何)。
布伦丹

@布伦丹:我不确定您的评论意图是表示同意,不同意,还是只是我的答覆。
布朗

专业人士编写的C程序会因缓冲区溢出和硬崩溃而释放。因此,尽管训练有素的程序员可以选择学习这些东西,但C语言并不是天生就仅因贫穷而教书。例如,有很多不好的方法(更糟糕的是,混合了多种不一致的方法)来进行无例外的错误处理并创建没有对象的结构。
Erik Eidt

@ErikEidt:的确如此,但是特别是在C生态圈中,有很多书籍,教程和其他材料可以解决这些主题。例如,史蒂夫·马奎尔(Steve Maguire)撰写的“ Writing Solid Code”。当然,如果有人只是选择了K&R的第一版来学习语言语法,他可能不会成为更好的程序员。
布朗

1

计算的两个基本抽象是图灵机和Lambda演算,而C是一种使用图灵机计算观进行实验的方法:大部分是一系列的低级动作,从中可以得出理想的结果。但是您必须记住,C附带了自己的计算模型。因此,学习C将教您C抽象机的低级细节,它与实际架构有很大的不同。用C语言教给我的第一件事是,从不尝试通过应用“聪明”的技巧使编译器胜于智能,而且似乎趋势是朝着越来越多的编译器进行优化。就像在其他高级语言中一样,当您使用C进行编写时,编译器会理解您希望在抽象C机器上完成的工作并使其在实际硬件上实现,

因此,我的意思是,学习C并不一定能使您充分了解硬件中实际发生的情况。“ C靠近机器”应理解为“比大多数高级语言更近”。如果您想更准确地了解“它是如何工作的”,直接学习软件体系结构将会带来更多的回报。

另一方面,学习C可以使您熟悉系统编程,低级类型,指针,尤其是内存分配。至于学习算法和数据结构,我没有用C而不是其他语言学习它们的优势。


1
那么,C可以教您什么高级语言无法做到?
菲利普·肯德尔

2
我认为隐性答案是:“ 没有,至少不是支持者通常要求的东西”。无论如何,这就是我理解答案的方式。
约尔格W¯¯米塔格

-3

这是一个很开放的问题,可能无法得出结论性的答案。只要您了解语言框架的内部结构,就可以学习几乎所有语言的所有内容。C强制您理解较低的细节,因为它主要是为编写操作系统而设计的。即使经过了这么多年,由于嵌入式系统和开源项目的缘故,它仍然是最常用的语言之一。那么,问题是您想学什么?在哪个领域?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.