我相信C是学习编程背后原理的好语言。对于那些与高级语言(如Ruby)“相去甚远”的低级语言,您打算学什么?
我相信C是学习编程背后原理的好语言。对于那些与高级语言(如Ruby)“相去甚远”的低级语言,您打算学什么?
Answers:
在计算机科学的一般抽象意义上,没有C语言中存在的,高级语言中也没有的原理。所有计算机科学都归结为算法,并且所有算法都可以用C一样具有图灵完备性的任何语言来实现。
C携带高级语言的区别类似于机器代码与C区别的区别:机器与代码的关系。
用高级语言编写代码时,您(通常)不必担心代码与计算机的交互方式。语言为自己定义的虚拟机隐藏了代码执行的许多方面。
在C语言中,程序与内存的交互始终处于最前沿。不仅仅是要管理堆的使用,还包括代码与堆栈的交互,以及代码对内存的访问如何影响代码的行为和性能,甚至不影响内存访问的顺序。可以避免引起您的注意,因为在错误的时间读取错误的内存可能会严重削弱性能。
在高级语言中,这些事情根本不那么明显。内存是在您不知情的情况下分配和释放的,有时是在您不提示的情况下进行的。通常,这完全是您无法控制的。大多数内存分配的时间,地点,方式和原因都对您完全隐藏了。
同样,从另一个方向看,编写机器代码或汇编代码将更多细节带到了前台:几乎没有什么东西不在您的权限范围之外,并且必须在编写代码时了解传递的每个分配,每个资源,每个数据段。通过CPU的寄存器-到目前为止,这些知识已从高级语言中删除,从而变得晦涩难懂。
我知道C是学习编程背后原理的好语言。
我不同意。C缺少太多功能,无法学习编程背后的原理。C创建抽象的功能很糟糕,抽象是编程背后的关键原理之一。
如果您想了解硬件的工作原理,从而对机器有所机械同情,则应该学习机器代码(又称指令集架构),并研究现代CPU的缓存结构。请注意,我不建议使用汇编语言,只需了解硬件说明,即可了解编译器生成的内容。
如果您想学习编程原理,请使用Java,C#或Swift等现代语言,或使用Rust等数十种其他语言之一。另外,研究各种编程范例,包括函数式。
大多数编程语言都是用抽象机来描述的。然后,使用诸如编译器,链接器,汇编器,解释器,静态分析器,中间语言和硬件之类的工具集来实现这些工具,这些工具将共同产生至少尊重抽象机所有预期行为的结果,如程序所观察到的那样。
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与70或80年代的那些好老车之一进行比较,它们只是为了驾驶而设计的。您可以将它们拆开,拧紧,并了解每个部分的工作方式,以及它们如何与您可以拿到手中的其他部分一起工作。一旦了解了所有部分,便可以清楚地了解整个过程。
现代语言更像是一辆现代汽车,其引擎基本上是一个黑匣子,太复杂了,普通车主无法理解。那些车可以做很多事情,在这些日子里,他们正在积极学习自己驾驶。由于具有这种复杂性和舒适性,用户界面已经远离引擎实际发生的变化。
当您学习用C语言编程时,您会接触到许多计算机组成的螺钉和螺母。这使您可以了解机器本身。例如,它使您能够理解为什么构建这样的长字符串不是一个好主意:
java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
result = result + components[i];
};
(我希望这是正确的Java,我已经有一段时间没有使用它了……)从此代码示例中,循环为什么具有二次复杂度并不明显。但是事实就是如此,这就是当您要连接数百万个小型组件时,此代码会停顿下来的原因。经验丰富的C程序员可以立即知道问题出在哪里,并且很可能一开始就避免编写此类代码。
for(int i = 0; i < strlen(s); i++)
使用C 编写,则循环也将具有二次复杂度,并且与Java示例中的代码一样显而易见;-)
有比C语言更好的语言来学习“编程背后的原理”,尤其是理论原理,但是C语言对于学习有关工艺的一些实用,重要的东西可能是一件好事。greyfade的回答肯定是正确的,但是恕我直言,与您自己管理内存相比,您可以从C中学习更多的知识。例如,
在没有异常的情况下如何创建具有完整错误处理的程序
如何在程序中创建结构而无需任何面向对象的语言支持
如何在缺少数据结构(如动态可伸缩列表,字典或有用的字符串抽象)的情况下处理数据
即使编译器或运行时环境未自动警告您,如何避免常见错误(如数组溢出)
如何创建通用解决方案,而无需模板或通用语言的支持
我是否提到过您可以学习如何自己管理内存?;-)
此外,通过学习C,您将了解C ++,Java,C#,Objective C的语法通用性从何而来。
在2005年,Joel Spolsky撰写了有关学习C 的建议,建议先学习其他高级语言。他的论据是
“您将永远无法使用高级语言创建高效的代码。”
“您将永远无法在编译器和操作系统上工作,这是周围最好的编程工作。”
“您永远不会被信任为大型项目创建架构”
“如果您无法解释为什么while(*s++ = *t++);
复制字符串,或者如果这不是世界上最自然的东西,那么,您是基于迷信进行编程的
当然,他的著作无疑是有争议的,但是恕我直言,他的许多论点在今天仍然有效。
计算的两个基本抽象是图灵机和Lambda演算,而C是一种使用图灵机计算观进行实验的方法:大部分是一系列的低级动作,从中可以得出理想的结果。但是您必须记住,C附带了自己的计算模型。因此,学习C将教您C抽象机的低级细节,它与实际架构有很大的不同。用C语言教给我的第一件事是,从不尝试通过应用“聪明”的技巧使编译器胜于智能,而且似乎趋势是朝着越来越多的编译器进行优化。就像在其他高级语言中一样,当您使用C进行编写时,编译器会理解您希望在抽象C机器上完成的工作并使其在实际硬件上实现,
因此,我的意思是,学习C并不一定能使您充分了解硬件中实际发生的情况。“ C靠近机器”应理解为“比大多数高级语言更近”。如果您想更准确地了解“它是如何工作的”,直接学习软件体系结构将会带来更多的回报。
另一方面,学习C可以使您熟悉系统编程,低级类型,指针,尤其是内存分配。至于学习算法和数据结构,我没有用C而不是其他语言学习它们的优势。
这是一个很开放的问题,可能无法得出结论性的答案。只要您了解语言框架的内部结构,就可以学习几乎所有语言的所有内容。C强制您理解较低的细节,因为它主要是为编写操作系统而设计的。即使经过了这么多年,由于嵌入式系统和开源项目的缘故,它仍然是最常用的语言之一。那么,问题是您想学什么?在哪个领域?