了解 C 实际上会损害您用高级语言编写的代码吗?
这个问题似乎已经解决了,甚至被打死了。聪明人在这个主题上说过聪明的事情。要成为一名真正优秀的程序员,您需要了解 C。
或者你呢?
这周我有两次开悟。 第一个 让我意识到我的假设并没有超出我的知识范围,而且考虑到我的机器上运行的软件的复杂性,这几乎不存在。但真正让人理解的是这条 Slashdot 评论:
最终结果是我注意到传统 C“裸机”程序员假设实现更高级语言的许多天真的方式。他们在他们影响的项目中做出了糟糕的“优化”决策,因为他们不知道编译器是如何工作的,也不知道一个好的运行时系统与他们理解的简单的宏汇编器模型有多么不同。
然后我突然意识到:C 只是又一个抽象,就像所有其他抽象一样。甚至CPU本身也只是一个抽象!我只是从未见过它破裂,因为我没有工具来测量它。
我很困惑。我的思想是否已经被严重破坏而无法恢复,就像 Dijkstra 对 BASIC 所说的那样?我是否一直生活在过早优化的状态中?既然我意识到自己对任何事情都一无所知,我还有希望吗?有什么需要知道的吗?为什么它如此令人着迷,以至于我在过去五年里写的所有内容都可能从根本上是错误的?
总而言之:了解 API 文档之外的内容还有什么价值吗?
编辑:制作CW。当然,这也意味着现在您必须发布比我们更好的解释器/运行时优化示例:)
The question seems settled, beaten to death even. Smart people have said smart things on the subject. To be a really good programmer, you need to know C.
Or do you?
I was enlightened twice this week. The first one made me realize that my assumptions don't go further than my knowledge behind them, and given the complexity of software running on my machine, that's almost non-existent. But what really drove it home was this Slashdot comment:
The end result is that I notice the many naive ways in which traditional C "bare metal" programmers assume that higher level languages are implemented. They make bad "optimization" decisions in projects they influence, because they have no idea how a compiler works or how different a good runtime system may be from the naive macro-assembler model they understand.
Then it hit me: C is just one more abstraction, like all others. Even the CPU itself is only an abstraction! I've just never seen it break, because I don't have the tools to measure it.
I'm confused. Has my mind been mutilated beyond recovery, like Dijkstra said about BASIC? Am I living in a constant state of premature optimization? Is there hope for me, now that I realized I know nothing about anything? Is there anything to know, even? And why is it so fascinating, that everything I've written in the last five years might have been fundamentally wrong?
To sum it up: is there any value in knowing more than the API docs tell me?
EDIT: Made CW. Of course this also means now you must post examples of the interpreter/runtime optimizing better than we do :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
不了解 C 语言或了解底层的实现细节都会对你造成伤害——就其本身而言。如果你始终按照低层次的细节思考和工作,即使这是不合适的,也可能并且将会伤害你。
老话说“真正的程序员可以用任何语言编写 FORTRAN”。如果您使用 C 做同样的事情,这并不是一个改进。如果你正在写 Lisp,就写 Lisp。如果您正在编写 Python,就编写 Python。对于 C 来说合适和合理的东西并不适合其中任何一个(或许多其他的任何一个)。
优秀的程序员需要能够在许多不同的抽象级别上进行思考,并且(更重要的是)识别并应用适合手头任务的抽象级别。
了解 C 的抽象级别不会有什么坏处。对替代方案的无知可以(并且将会)。
Neither knowing C nor knowing the lower-level details of implementation hurt you -- in themselves. What can and will hurt you is if you consistently think and work in terms of the low-level details, even when it's inappropriate.
The old saying was that "real programmers can write FORTRAN in any language." If you do the same using C, it's not an improvement. If you're writing Lisp, write Lisp. If you're writing Python, write Python. What's appropriate and reasonable for C is not for either of those (or any of many others).
A great programmer needs to be able to think at many different levels of abstraction, and (more importantly) recognize and apply the level of abstraction that's appropriate to the task at hand.
Knowledge of C's level of abstraction doesn't hurt. Ignorance of alternatives can (and will).
知识没有坏处。曾经。
那些用高级语言写出糟糕代码的人是因为他们没有正确掌握高级语言,是糟糕的开发人员。
knowledge doesn't harm. ever.
Those that wrote bad code in higher level language is because they didn't master properly the higher level language, bad developers.
对于糟糕的开发人员来说,任何类型的知识都可能是危险的。
对于优秀的开发人员来说,任何类型的知识都是一种资产。
To a bad developer, any type of knowledge can be dangerous.
To a good developer, any type of knowledge is an asset.
使用语言——自然的(口语)或人工的(编程)——需要大脑以某种方式适应。每种语言都有自己的语法、自己的词汇表(API)等。如果您主要是 Java 程序员并转向 Ruby,那么您至少会遵循 Java 程序员的思维模式,即使不编写基本上是 Java 代码的内容红宝石。需要付出一些努力和练习,才能开始适应新环境(Ruby 语法、Ruby API)并开始编写 Ruby 代码。
因此,这个过程是完全正常的,之前模式的任何不利影响都是非常短暂的。更重要的是,您学习的每一种语言都会拓宽您的视野,并使学习下一门语言变得更加容易。享受旅程。 :]
Using languages - natural (spoken) or artificial (programming) - requires the mind to adapt in a certain way. Each language has it's own grammar, it's own vocabulary (APIs) etc. If you're mostly a Java programmer and switch to Ruby, you will at least follow the thought patterns of a Java programmer, if not write what is basically Java code in Ruby. It takes a bit of effort and practice until you begin to feel comfortable in the new environment (Ruby grammar, Ruby APIs) and start writing Ruby code.
So, the process is perfectly normal and any adverse effect of previous patterns is very short lived. What's more important, every language you learn broadens your horizons and makes learning the next one easier. Enjoy the journey. :]
编程与编程语言无关。这是关于解决问题。用于解决问题的工具恰好是编程语言。您编写代码不是为了编写代码,而是为了执行代码并解决问题。
您对工具了解得越多,就能更好更快地解决问题。但是,虽然当您尝试用锤子将螺丝钉入木头时会遇到严重的麻烦,但软件有一个很好的特性:对于任何给定的问题都有无数种不同的解决方案。
因此,完全有可能编写一个锤子,以这样的角度敲击螺钉,螺钉会告诉木头在自身上打一个孔,以便螺钉适合。然后你可以将它隐藏在按钮后面,用户不需要甚至不需要知道锤子到底是什么。
虽然它不是最有效的解决方案,但它仍然是一个有效且可行的解决方案。当您更好地使用所使用的工具时,最终您会发现在 API 不提供螺丝刀的情况下如何编写螺丝刀。
您了解的工具越多,解决问题的方法越多,您的选择就越多,您对使用哪种解决方案的决定也就越准确。为工作选择正确的工具。但是,当您不知道工具和可能的解决方案时,您怎么能呢?
Programming is not about programming languages. It is about solving problems. The tools used to solve the problems just happens to be programming languages. You don't write code to write code, you write code to execute it and solve the problem.
The better you know your tools, the better and faster you can solve the problems. But while you will have serious trouble when you physically try to drive a screw into wood using a hammer, software has a nice property: There are an absurdillion different solutions to any given problem.
So it is perfectly possible to write a hammer that hits a screw in such an angle that the screw will tell the wood to make a hole into itself so that the screw fits in. Then you can hide it behind a button, the user doesn't even need to know what a hammer actually is.
While it is not the most efficient solution, it is still a valid and working solution. When you get better with the tool you've used, finally you will discover how you can write a screwdriver when the API doesn't provide one.
The more tools you know and the more ways you know how to solve any problem, the more choice you have and the better your decisions about what solution to use will be. Chose the right tool for the job. But how could you when you don't know the tools and the possible solutions?
扩展其他人的评论......虽然我不确定我是否相信 http://en.wikipedia.org/wiki/Whorfian_hypothesis">Whorfian 假说,当涉及到自然语言时,它显然是正确的谈到编程,你所知道的语言会影响你解决问题的方式:
1)来自我很多年前的一位教授:他试图找出他的字符串数组中是否有重复项。 70 年代,他用 FORTRAN 写了这个。他的蛮力 n^2 实现花费了太长时间,所以他的朋友知道 PL1(我认为是,也许是 APL),它有一个排序运算符。因此,在这种语言中,您可以学习对事物进行排序,这非常有用,因为朋友首先提出了明显的排序,然后查看相邻元素算法,速度要快得多,而且不会想到。我的 FORTRAN 写作教授,尽管它在 FORTRAN 中完全可以实现
2)当我在读研究生时,我有一个物理研究生的室友。他去了麻省理工学院,只上了一门编程课,当然是在Scheme中。有一天,我去了他的办公室,他说:“嘿,布莱恩,你能看一下这段代码并告诉我它是否有效吗?”这是一个排序程序。我看了一眼,说它不可能工作,因为它显然是冒泡排序,但它只有一个循环(不,如果你生病了,这不是一个可以用来编写冒泡排序的时髦循环)扭曲)。所以,我这么说。他回答说:“哦,但是它在底部有一个递归调用!”我从来没有想到要写一个递归冒泡排序。但更重要的是,他从来没有想到要编写一个非递归函数!
关键是您所了解的语言在很大程度上决定了您将编写的代码类型。你知道的语言越多,你拥有的工具就越多,而且更多的工具从来都不是坏事,只要你知道何时使用它们......
To expand on other's comments... While I'm not sure that I believe in the http://en.wikipedia.org/wiki/Whorfian_hypothesis">Whorfian Hypothesis when it comes to natural languages, it's pretty clearly true when it comes to programming. The languages you know affect how you solve a problem. Two examples:
1) From a professor I had many many years ago: He was trying to find out if there were any duplicates in his array of strings. This in the 70's so he was writing this in FORTRAN. His brute force n^2 implementation was taking way too long. So he spoke to a friend. His friend knew PL1 (I think it was, maybe it was APL) which has a sort operator. So, in that language, you learn to sort things, and how useful that can be, because it's easy. The friend came up with the obvious sort first, then look at adjacent elements algorithm. Much faster, and it would not have occurred to my FORTRAN writing professor, even though it was perfectly implementable in FORTRAN.
2) When I was in grad school, I had a Physics grad student for a roommate. He went to MIT, and only took one programming class, which was of course in Scheme. One day, I stopped by his office, and he said "Hey, Brian, can you take a look at this code and tell me if it should work?" It was a sorting routine. I glanced at it, and said it couldn't possibly work, because it was clearly bubblesort, and yet it only had one loop (and no, it wasn't the one funky loop that you can write bubblesort with if you are sick and twisted). So, I said that. He responded "Oh, but it has a recursive call at the bottom!" It never would have occurred to me to write a recursive bubblesort. But more importantly, it never would have occurred to HIM to write a non-recursive function!
The point being that the languages you know, determine to a large extent, the kind of code you will write. The more languages you know, the more tools you have, and more tools are never bad, as long as you know when to use each of them...
我同意这一点。
但我也同意,要成为一名真正优秀的程序员,您必须真正知道如何用另一种语言编写代码(而不是如何编写另一种语言的 C 代码)。
I agree with this.
But I also agree that to be a really good programmer, you have to really know how to write code in another language (not how to write C code in another language).
了解 C 不会损害代码的质量,但了解“仅 C”肯定会损害代码质量
Knowing C will not hurt the quality of your code, but knowing "only C" for sure will
不。
如果你失去了求知和进步的欲望,尽管你受到了伤害。
no.
If you lose your desire to know and improve though you are damaged.
软件工程是关于理解抽象以及如何使用抽象来有效地解决问题(无论有效意味着更低的成本、更快的性能还是最短的交付功能的时间表)。理解 C 只是对我们使用的抽象层的另一种见解。只要您还培养了必要时“缩小”的技能,“放大”到这种细节级别所需的技能就很有价值。该技能集将在该学科的各个方面为您提供良好的服务,无论是设计对象模型、设置干净的功能组合,还是只是为了清晰度和可维护性而构建单独的方法。
Software engineering is about understanding abstraction and how to use abstraction to solve a problem efficiently (whether efficiently means lower cost, faster performance or shortest schedule to delivery of the functionality.) Understanding C is just another insight into a layer of the abstraction we use every day and the skill required to 'zoom in' to this level of detail is valuable, as long as you also develop the skill to 'zoom out' when necessary. This skill set will serve you well in every aspect of the discipline, whether it's designing an object model, setting up clean functional compositions, or even just structuring an individual method for clarity and maintainability.
了解不同语言是一项资产。了解编译器和解释器是如何构建的也是一项资产。最后,每个程序员都应该花一些时间学习汇编语言,以欣赏更高级的语言。 :-)
在我的大学,我们选修了一门“编程语言”课程,我们在其中学习了 LISP、SNOBOL 和 ADA。这些语言让你在解决编程问题时能够接受不同的概念思维。总结就是选择最适合问题的语言。
了解编程语言只是基础。如果我不了解其他相关主题,我的职业生涯就不会走得太远:数据结构、算法、线性代数、布尔代数、微处理器设计和通信(人与人之间)。任何人都可以拿起一本书,学习一门语言并称自己为程序员。正是这些其他技能将熟练的开发人员与普通开发人员区分开来。
学习一门编程语言。学好它,这样你就可以将更多的脑力集中在手头的其他任务上。您不应该经常参考编程手册。我的大部分注意力都集中在任务的要求以及算法和数据结构上,以使其在最短的时间内正确实现。
Knowing different languages is an asset. Knowing how compilers and interpreters are built is also an asset. Finally, every programmer should spend some time in assembly language to appreciate the higher languages. :-)
At my university, we took a class, "Programming Languages", in which we learned LISP, SNOBOL and ADA. These languages open your mind to different conceptual thinking in solving the programming problems. The summary was to choose the language that best fits the problem.
Knowing a programming language is only the foundation. I would not be very far in my career if I didn't know other related topics: Data Structures, Algorithms, Linear Algebra, Boolean Algebra, Microprocessor Design and Communications (between people). Anybody can pick up a book, learn a language and call themselves a programmer. It's the other skills that differentiates a skilled developer from one pulled off the street.
Learn a programming language. Learn it well, so that you can focus more brain power on the other tasks at hand. You should not be referencing a programming manual often. Most of my concentrations are on the requirements of the task and the algorithms and data structures to get it implemented correctly in the least amount of time.
简短而甜蜜:
要成为一名优秀的程序员,您需要能够以有组织的方式思考。 C 或 LUA 或 Java,等等。
Short and sweet:
To be a good programmer, you need to be able to think in an organized way. C or LUA or Java, whatever.
如果您将这些知识应用于实际上不需要的高级语言,那么只会带来伤害。当然,凭借一些编写自己的集合类的低级 C 经验,我也可以使用 Java 等语言来实现这一点。但它会是现有 Collections 库(Java API 和 Commons Collections 附加功能)的更好替代方案吗?或许。
在实践中,您必须计算投入的时间是否值得。
事实上,您应该在修改代码之前简单地进行研究。看看是否可以使用内置或第三方工具来完成您想要做的事情。如果可以的话,看看内置工具或第三方工具是否能满足您的要求,以及它们是否表现良好。如果他们不这样做,找出原因。如果他们/真的/不这样做,请重写。
正如其他人所说,所有知识都是有价值的。我的意思是 /all/ - 既是低级优化的 C 代码,也是对开发良好的库的高级调用。如果您了解两者,您就会知道何时使用哪一个以及为什么使用哪一个。
It'll only hurt if you apply that knowledge to higher-level languages when it really isn't required. Sure, with some low-level C experience in writing my own collection classes, I could also do that in, say, Java. But would it be a better alternative to the existing Collections library (both the Java API as the Commons Collections extras)? Maybe.
In practice, you'd have to calculate if the time invested is worth it.
In truth, you should simply do research before hacking away at your code. See if what you're trying to do can be done using built-in or 3rd party tools. If you can, then see if the built-in or 3rd party tools do what you want, and if they perform good. If they don't, find out why not. If they /really/ don't, rewrite.
As others has stated, all knowledge is worthwhile. And with that I mean /all/ - both the low-level optimized C code, as the high-level calls to well-developed libraries. If you know both, you will know which one to use when, and why.
不,了解编程语言的多种实现只能帮助您更好地理解这些抽象。
问题是你接受了一个最好抽象,这将导致你无法成功地使用其他你认为次要的抽象。
每个抽象都是针对特定的不同目标而设计的,请选择最适合您需求的一个。了解 Linux 是否会让了解 Windows 或 Mac 操作系统变得更困难?这是接受他们不同。
No, knowing multiple implementations of a programming language can only help you understand those abstractions better.
The problem is is you accept one to be the best abstraction that will cause you not to succeed using the others you perceive to be lesser.
Each abstraction is designed with a specific different goal, choose the one that works best for your needs. Does knowing Linux make knowing Windows or Mac OS harder? Its the acceptance that they are different.
这里真正的问题是假设。其他开发人员假设他们知道它是如何工作的。假设是魔鬼,无论是来自认为自己已经解决了所有问题的经验丰富的开发人员,还是来自认为自己已经解决了所有问题的新手。
至少,这就是我在这里假设的
The real problem here is assumption. Those other developers assume they know how it works. Assumptions are the devil whether it's from an experienced dev who thinks they have it all figured out or from a newbie who thinks they have it all figured out.
At least, that's what I'm assuming here
学习C是一件好事。尝试用高级语言编写 C 代码是一件坏事。
Learning C is a good thing. Trying to write C code in a higher level language is a bad thing.
学习 C(或任何与此相关的语言)可能会对程序员造成伤害,这似乎取决于你在学习 C 后无法再学习任何东西。这里的教训应该是不要停止学习。此外,不要假设任何其他语言或技术一定可以像 C(或您最喜欢的 C 编译器)一样工作。
也就是说,我认为学习 C 语言是了解硬件如何工作以及机器中实际发生的情况的好方法。我看不出知道这一点会对你造成任何伤害。我不认为无知有任何好处(除非它们是偶然的)。我承认学习 C 语言并不是了解机器的唯一方法,但它只是其中的一种方法。
That learning C (or any language for that matter) could hurt you at a programmer seems to hinge upon you not being able to learn anything after having learned C. The lesson here should be don't stop learning. In addition, don't assume that any other language or technology necessarily works like C (or your favorite C compiler).
That said, I think learning C can be a good way to learn how hardware works and what is actually occurring in the machine. I can't see how knowing this could hurt you in any way. I don't think being ignorant has any benefits (unless they are accidental). I do admit that learning C is not the only way to learn about the machine, but it is merely one way to do so.
了解多种语言/框架和编程范例永远不会有坏处——它应该是有益的。
重要的是要了解您当前正在使用的语言/框架/环境,以便了解做出实施选择的含义。在这里,使用其他语言获得的知识可能会让您看到更广泛的可能性 - 但您必须根据当前环境评估这些可能性。
那些让自己陷入真正麻烦的人是那些学习了某种语言(例如 C)的人,然后根据 C 语言学习另一种语言,而不是根据其自身的优点、优点和缺点来学习它(有点像拿着锤子的杂工)作为他唯一的工具 - 所有问题对他来说都像是钉子)。
Understanding multiple languages/frameworks and programming paradigms should never hurt - it should be beneficial.
The important bit is to understand the language/framework/environment you are currently working in to the extent that you know the implications of making implementation choices. Here, knowledge gained in working with other languages may open your eyes to a wider range of possibilities - but you have to evalutate those possibilities in terms of your current environment.
The folks that get themselves into real trouble are those that learned some language, C for example, and then learn another language in terms of C as opposed to learning it for its own merits, strengths and weaknesses (kind of like the handyman with a hammer as his only tool - all problems look like nails to him).
例如,了解 C,然后使用我最喜欢的超高级语言 (Python) 工作,这就是为什么我发现了解 C 很有帮助的一个例子。
当我使用 Python 时,了解 C 在几个方面都有帮助
:( )我感谢 Python 的列表、字典和内置类型,因为它使我可以轻松地在一行代码中重复执行某些操作,这需要我选择一些代码库,学习它并链接到它(哈希表、数据结构等),避免搬起石头砸自己的脚。
(b) Python 是用 C 编写的。作为一名 C 程序员也意味着,如果 Python 让我完成了 99% 的工作,但一些额外的抽象在 Python 中可能会很方便,我可以用 Python 编写该抽象。我可以查看 CPython 解释器的源代码并了解内部发生的情况。实际上,作为一名 Python 程序员,我仍在使用基于 C 语言构建的东西。因此,了解语言仍然很有价值。
我上面所说的一切也适用于使用 Perl、Ruby 和 PHP 的人。
Knowing C, and then working in my favorite very-high-level language (Python), for example, is an example of why I find it helpful to know C.
Knowing C, when I use Python is helpful in several ways:
(a) I am thankful for Python's lists, dictionaries, and builtin types, because it makes it easy to do something, repeatably, in one line of code, that would require me to select some code library , learn it, and link to it (hash tables, data structures, etc) and avoid shooting myself in the foot with it.
(b) Python is written in C. Being a C programmer also means, that if Python gets me 99% of the way there, but some additional abstraction might be handy in python, I can write that abstraction in Python. I can look into the source code of the CPython interpreter and understand what is happening internally. I am, in effect, as a python programmer, still using something built atop the C language. Thus, knowing that language is still valuable.
Everything I said above is also true of people using Perl, Ruby, and PHP.