C 对于 Java 程序员来说是什么?

27

可能是重复问题:
我应该先学习C还是C++?

作为一名专业的(Java)程序员和 Linux 用户,我觉得学习一些 C 是我的责任(即使我可能永远不会在职业上使用它),这样可以让我成为一个更好的编程人员。

两个问题:

  1. 我应该先尝试 C 还是 C++ - 我意识到它们是不同的语言,但有一些共同点。学习一点 C++ 是否有用,还是只尝试其中一种?我听说 C++ 是一个庞大的噩梦语言。

  2. 对于像我这样的 Java 开发者,最好的资源是什么(书籍、教程、实践程序、参考代码)?

谢谢


11
感谢您认识到自己的责任,给您点个赞;) - Aiden Bell
2
我意识到这个评论并不是世界上最有用的...但你有没有尝试过搜索这两个问题的答案?我们已经看到这些问题很多次了。 - KevenK
7
对我而言,C语言是一种相当简单且优雅的低级语言,我喜欢使用它。至于C++嘛...好吧,我不想伤害任何人的感情。(顺带一提,我也是Java程序员。) - Nikita Rybak
1
@Aiden 嗯,我在寻找一些更有力的词语,比如那个与“morrible”押韵的词 :) - Nikita Rybak
1
不要学习这两种语言。学习一种完全不同的语言。我建议学习一些函数式编程语言,比如Lisp。Scheme也有一些好书可以参考。 - Dennis Zickefoose
显示剩余9条评论
7个回答

33

C语言简单易学,但是掌握难度很大。如果你是一名Java程序员,那么内存和结构将是阻碍。而且还需要消除Java对你的大脑算法产生的影响 ;)

我建议你通过互联网上的教程,熟悉Linux下的GCC工具链。然后阅读《C程序设计语言》,并且可以看一下《Linux应用开发》。在Linux上,glib可以帮助你避免重复造轮子...但至少要尝试创建自己的链表、哈希表、图形和其他API来学习。指针运算、数组以及了解结构体等元素只是二进制块中的命名偏移量都非常重要。花时间使用mallocfree和memcheck。在学习时,你的工具和工具链非常重要,IDE不一定是你的朋友。

相比C++,我会选择C作为基础语言,因为它可以让你逐步习惯于C的内存管理和指针用法。

你可以通过将所学应用到实际项目中来获得最好的学习效果。但是要准备在ValgrindGDB中花费很多时间。我已经使用C语言编程多年,但仍然不是一名C语言高手。

我同意C语言是一门伟大的语言,它可以揭示出糟糕的程序员。但请记住:

任何足够复杂的C程序都包含一个特定的、非正式的、错误丛生的、速度缓慢的Common Lisp的一半实现。

这个故事的寓意是学习其他编程语言,而不仅仅是C语言的衍生语言!考虑一些Lisp方言、Erlang(目前很流行)和Haskell等。它们将会拓展你的视野,让你走出Java的2x2单元格。同时,建议看看SICP


2
嗯,掌握C并不是特别困难。C++很难掌握,这基本上就是为什么C更适合某些项目的原因。 - jalf
我同意,已经在学习Clojure的过程中了 ;) - lucas1000001
6
@jalf - 我不同意。C语言确实简单,但美在于应用和优雅。掌握技能是制作出漂亮的C程序,而不是那些处理内存和逻辑像垃圾一样的程序。 - Aiden Bell
我不同意在学习C++之前要先学习C语言,特别是对于那些有面向对象/Java编程背景的人来说。这里的帖子可能会帮助他做出决定,我建议学习C++而不是C语言。https://dev59.com/L3VC5IYBdhLWcg3w7Vxq#145098 - KevenK
1
@Aiden:C语言易学是它被用于Linux内核的主要原因之一:他们需要一种人们可以轻松掌握并使用,同时编写相对稳定代码的语言。我的观点只是,尽管我更喜欢C++,但C肯定更容易掌握。 - jalf
显示剩余3条评论

27
  • Understanding and mastering pointers, memory allocation, and management.
  • Understanding the concept of headers, includes, and linking.
  • Understanding data types and structures.
  • Understanding basic algorithmic principles such as sorting and searching.
  • After getting a solid foundation in C, learning C++ becomes much easier because it builds on top of C and provides additional object-oriented programming features.

    In conclusion, while transitioning from Java to C/C++ may be challenging, starting with C can help build a strong foundation for understanding the lower-level aspects of programming and make the transition smoother.

  • 指针 Java 当然使用指针,但在传递类时隐藏了其访问。在 C 中,你将需要学习按值和按引用的区别。还有更微妙的区别,如 char x[3] 和 char *x = "ab"。以及通过指针方便地遍历数组等等,您知道*++x 或 *x++。关于指针已经说了很多,我的建议是:

    1. 始终保持控制,即不必要时不要放置太多间接。
    2. 不要 typedef 指针,例如 typedef int *pointerToInt;起初似乎更容易(使用 pointerToInt pi 而不是 int *pi),但经过几个级别后,我宁愿数星星而不是“pointerTo” [一些大公司也这样做]。除非是指向函数的指针,否则根本无法阅读。
  • 内存 当您需要内存时,分配它,当您不再需要它时,释放它。简单。问题在于分配正确的数量,并且不要多次释放它... 必须习惯。并且要习惯堆栈... 当您的程序运行并且地址为 NULL (0) 时,您可能会看到一个异常。也可能没有。

  • 数据结构 所以你想使用方便的 HashMap?当然,在你开发它之后。或者有一些库可以链接并完成这种事情,只需选择正确的一个。公平地说,当在 C 中编程时,您 [必须] 思考不同,并且可能会找到比地图更适合某个问题的更合适的算法。

  • 总的来说,起初您会感到迷失方向,但最终(除非您做噩梦)您会找到很多有趣和愉悦的空间。 C 允许一个人完全自由地编程:C 按照你的思想行动,而不是相反。


    哈哈,你说得对,错误通常会被埋在大量的堆栈跟踪/线程转储中。但我认为,大多数内存问题可以通过花费一些时间在分析器中来解决。这是Java程序员避免内存泄漏的必要学习经验。 - TheLQ

    11

    如果目标是成为更好的程序员,请选择那些真正尝试区别于其他语言的编程语言。Java、C++和C都紧密相关。

    确实,其中一种是主要的过程式语言,另一种则努力伪装成面向对象,还有一种则混合了至少4种不同的范式,但它们都是命令式语言,它们共享大量的语法,基本上它们都属于同一类语言。

    学习C并不能教你什么非常新的东西。它可能会教你一些关于内存布局之类的知识,但你可以用许多其他方式学习它,而且对Java程序员来说这并不是非常相关的。

    另一方面,这门语言相对容易掌握,并且广泛用于许多Linux软件,所以如果你想为任何这些软件做出贡献,学习C是一个好主意。只是它并不能使你成为一个更好的Java程序员。

    至于C ++,把它称为“噩梦般的庞然大物”的说法可能不远离事实。它很大、很复杂,充满了奇怪的陷阱和坑,对于初学者来说很难。

    但它也有一些可取之处。首先,它是少数支持通用编程范式的语言之一,这使得您可以非常简洁地表达许多高级概念,并具有高度的灵活性和代码重用性。

    它可能会让你因为被过度设计的混乱感到憎恨C ++,而且它还会让你因为其他语言缺少C++的功能而感到失望,这些功能本来会让你的代码更加简单。

    再次强调,学习C ++对于你作为Java程序员并没有太大的区别,除了它将揭示出一些你之前不知道的Java的问题。

    学习任意一门语言都是好的,但更好的是学习一些不同的东西

    学习SML或Scheme或Haskell。或者Ruby、Python或Smalltalk。怎么样Erlang或Occam?或者Prolog。

    学习一些既不是Java的兄弟也不是祖先,完全从头设计不与Java有任何相似之处的东西。比如学习一个函数式语言,如SML,或一个动态类型语言,如Python,或者一个彻底改变处理并发方式的语言,如Erlang。


    1
    +1:这句话表达了我想说的一切,但我不想在评论中表达。 - Dennis Zickefoose
    +1 很棒的帖子。我会加上Clojure作为一个选项 - 它是一种完全不同的语言范式,与Java(函数式、动态、并发、Lisp)完全不同,但它在Java平台上运行,所以对于Java开发人员来说,至少理解环境相对容易。 - mikera

    7
    1. 这取决于你想要学习什么。我认为最好的方法是坐下来考虑一下为什么你真的想做这件事。如果Java能够满足你的需求,而你只是出于某种错误的责任感而这样做,我认为有更好的方式来利用你的时间。C++作为一个“噩梦巨兽”的声誉主要是由于不安全的Java程序员试图证明他们心中知道是次优选择的东西1
    2. 有一些专门为Java程序员编写的书籍,介绍学习C和/或C++的内容。虽然它不是专门为Java程序员编写的,但如果你决定使用C++而不是C,我建议考虑Acclerated C++
    我当然只是开玩笑,但有很多Java程序员似乎都有些自卑。如果你告诉使用Python或Ruby的人(只举几个例子),它们很慢,典型的反应是他们看起来有点困惑,然后说:“如果你这么说的话——对我来说它似乎够快了。”建议Java也是一样的,几乎肯定会产生你显然无知、只表达盲目仇恨的声称。
    编辑:关于选择C和C++之间的区别,对于习惯于Java的人来说,C将仅仅是一种挫败感的练习。语言上的差异需要相当大的调整,但从Java这样的库到C这样的库的移动将简单地破坏他的生产力相当长的一段时间,并且更可能只是使他对所有带有“C”名称的语言产生偏见,而不是真正帮助他学到任何东西。
    直接从Java转向C就像把一个以林肯城镇车代替豪华轿车为体面的人,当他决定赛车很酷时,你直接把他扔进Outlaw sprint car的座位里。先给他一个机会在(不仅更安全,而且实际上更快)合法的赛车上试一试...

    如果你这么说的话——对我来说,Java程序员看起来很正常。 - President James K. Polk
    嗯,如果你周围都是疯子,我相信他们看起来也很正常。;) 我绝对能理解杰里在说什么。不管Java是否实际上是二流语言,Java程序员似乎经常有某种自卑感,就像他们觉得只有学了C++才算是“真正”的程序员。Python、Ruby或Haskell程序员可能根本不关心像C++这样的原始语言,而Java程序员似乎经常觉得他们走了“捷径”,这会给他们带来负面影响。 - jalf
    @jalf,C/C++给予Java的声誉以及它被大多数学校视为“入门语言”的标签。我告诉你,我有点受此影响,这促使我学习了C#。Python的不同之处在于它是动态的、新颖的和非常流行的。 - TheLQ

    5
    关于(1),我可能会说C。它更加陌生。由于你的目标是为了自身而学习多种语言,转向与Java非常不同的语言可能比学习C++更有用,后者可能会让你感到愤怒。C++受到很多人的诟病,但并不一定糟糕,主要原因是它试图将新范式强制加入C的结构中,这不如从一开始就以该范式为基础的语言好用。
    对于(2),我强烈推荐K&R。它假设你具有一定的编程知识,简洁明了,但也足够深入地解释概念。然而,它不包括练习题,你需要在其他地方找到。我恐怕是在工作中学习C的(仍在付出代价!),所以无法给你提供有根据的帮助。

    4

    既然你是为了自我实现和学习,我建议你可以尝试一下C++。

    在我详细解释之前,先简单说一下我的背景:我以前主要使用C++进行工作,并且从未处理过任何规模的C代码。现在我主要使用C#,只在极少数情况下使用C ++。

    我认为选择C ++ 是更好的选择,因为:

    • 它是C的超集: C程序通常不会编译为C++程序,但两种语言之间的重叠部分足够大,您应该可以重新定位您的技能以处理C代码(如果需要)。
    • C ++将向您介绍更多概念: 您将获得所有有趣的内存管理和位操作,这些都可以在C中完成。但您还将看到泛型,如您从未见过的那样,可以独立于容器编写算法,如何进行编译时多态性,如何多重继承有时可能非常有用等。
    • 您将更加欣赏Java语言的设计: C ++是一种复杂的语言,具有许多陷阱和边缘情况(请参见FAQFQA)。通过亲身体验,您将能够更好地理解Java和C#的许多设计决策。

    归根结底:学到的越多,你就能学到更多。而C ++会强迫你学习很多东西,肯定比C多。这是一件好事。


    2

    C++相对于C来说可能更加熟悉,也更容易上手。但是,C语言更小巧,学习起来应该相对简单(不过要注意,学习C语言可能会导致永久性的脑损伤)。我个人推荐使用Harbison & Steele的《C: A Reference Manual》(目前为第五版)作为C语言参考书。对于C++,我只使用O'Reilly nutshell book。

    作为一名有一些C++经验并正在转向Java的C程序员,我可以告诉你,关于C语言,以下几点可能会让你立刻陷入困境:

    • C语言中很少有抽象的概念;指针和字节流基本上就是全部了。没有标准的容器类型(比如列表、映射等)。如果你需要任何比固定长度数组更复杂的东西,你必须自己编写(或使用其他人开发的库)。
    • C语言中没有垃圾回收机制。每个你通过malloc()calloc()动态分配的字节都需要你负责释放(通过free())。
    • C语言中的数组与Java中的数组行为不同;在数组类型方面存在一些奇怪的规则,这些规则一开始看起来没有意义(直到足够的脑损伤发生为止)。数组没有边界检查,一些标准库函数(特别是gets()scanf())会导致缓冲区溢出漏洞成为真正的风险。
    • C语言中的声明语法可能会变得非常复杂。虽然你可能不会看到像int *(*(*f)())[10])();这样丑陋的声明,但类似于f是指向返回指针的10元素数组的函数指针这样的声明是可能的。
    • C语言的实现限制因平台而异;例如,语言标准仅规定了像shortintlong等类型的最小范围,但它们可能比最小要求更宽。如果你期望一个int在任何平台上都具有相同的大小,那么你会有些惊讶。
    • 在C语言中进行文本处理很麻烦。说真的,真的很麻烦。C语言没有字符串类型。

    有第三方库可用作 C 语言的垃圾回收器。 - Donal Fellows

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接