【问题标题】:Resources for learning C program design [closed]学习 C 程序设计的资源 [关闭]
【发布时间】:2010-10-29 20:55:53
【问题描述】:

来自 OO 背景 (C#/java) 我正在寻找资源来学习如何很好地设计纯 C 程序。

虽然我熟悉 C 的语法,并且我可以编写小程序,但我不确定大型应用程序采用的方法,以及采用什么技术。大家有什么可以推荐的。

编辑:我很高兴完全放弃 OO 以使用 C 编程,我的兴趣是学习如何在没有 OO 的情况下构建程序,我想了解用 C 等过程语言设计程序的好方法.

【问题讨论】:

  • 学习 C 可能是您可以做的最好的事情之一,以真正扩展您的技能。我知道这可能不是现在许多“现代”程序员习惯听到的,但这是真的。我认为你渴望学习它是一个非常聪明的举动。
  • 真棒的问题,我在同一个位置。 C 本身相当小,但是在编写较大的应用程序时,我也被困在如何设计它们...

标签: c


【解决方案1】:

这里有一些 interesting responses 来自关于 C 中的 OO 编程的另一个问题。我发表了一篇关于我使用的一些 C 代码的帖子,这些代码基本上通过不包含虚拟方法来实现面向对象的停止。

如果我在进行 C 编码,我会使用这种技术来定义“对象”。

我发现牢记Design Patterns 总是有帮助的,并且可以在大多数语言中实现。

这是一个很好的 PDF 讨论 object oriented C programming。

【讨论】:

  • 如果你想在 C 中做 OO,你真的应该使用 C++。如果你想使用 C,你应该编写漂亮、清晰的程序代码。
  • "如果你想使用 C,你应该编写漂亮、清晰的程序代码。"你能推荐任何资源来学习如何做到这一点吗?这就是我正在寻找的东西。
  • 在某些情况下需要使用 C。并非所有处理器都有 C++ 编译器——尤其是当您进入嵌入式环境时。当您使用在低级硬件上运行的代码时,最好还是用 C 编写代码,然后使用 C++ 包装器。
  • C 中的 OOP 主要归结为将对象实现为结构,将方法实现为具有显式实例指针参数的独立函数。这类似于其他语言处理 OOP 的方式,因此您调用 METHOD(object, arg1, arg2 ...)。当然,使用函数指针也可以实现更常见的 obj.method(arg1,arg2) 方法。
  • 如果你跳过使用函数指针,而采用传入对象结构指针的方法,那么你的代码就更具可读性 =)
【解决方案2】:

由 tanenbaum 制作的 minix

【讨论】:

    【解决方案3】:

    This posting 有一个 UNIX 书籍列表,其中包括大多数经典的 C/Unix 作品。对于 Windows 上的 C 编程,Petzold 的Programming Windows 可能是最好的开始。

    对于 C 程序设计,一些 UNIX 编程书籍会告诉您 sn-ps,但我不知道有一本“C 程序架构”书籍。

    如果你习惯 java,C 编程的一些技巧是:

    1. Makeuseofstack。通常,当您调用一个过程时,您会希望在调用者的堆栈帧中分配变量并将指向它们的指针传递给您要调用的过程。这将比使用malloc() 动态分配内存要快得多,而且更不容易出错。在适当的地方执行此操作。

    2. C 不做garbage collection, 所以动态分配数据项更加繁琐,你必须跟踪它们到make sure they get freed. 在堆栈上分配的变量(参见 1)在它们的位置更“惯用”适用。另外,您不必释放它们 - 这是局部变量的好处。

    3. 根据 (2),考虑一种架构,其中您的函数返回状态或错误代码,并按照 (1) 使用堆栈传入和传出数据。

    4. 了解setjmp() 和longjmp() 的作用。它们对于代替结构化异常处理功能的通用错误处理机制非常有用。

    5. C does not support exceptions. 见(3)。

    6. Lint 是你的朋友。 Splint 更友好。

    7. 了解preprocessor 的作用以及即使可以使用它也不应该做的事情。

    8. 了解endian-ness、word alignment、pointer arithmetic 和其他低级架构奥秘的来龙去脉。与流行的观点相反,这些都不是火箭科学。如果您感觉很热,请尝试涉足汇编语言并获得相关的工作知识。它将有助于您了解 C 程序中发生的事情。

    9. C 没有模块范围的概念,因此请计划好使用包含、原型声明以及使用 extern 和 static 来创建私有范围和导入标识符。

    10. allplatforms. 上的 C 语言 GUI 编程很乏味

    11. (10)的建议学习至少一种脚本语言的C API 如Tcl、Lua 或Python. 在很多情况下,C 的最佳用途是作为核心高性能引擎上的应用程序基本上是用其他东西编写的。

    12. 构造函数的等价物是一个初始化函数,您可以在其中传递一个指向要设置的项目的指针。通常,您可以通过调用类似于 setup_foo(&my_foo) 的函数的形式看到这一点。最好将分配与初始化分开,因为您可以使用此函数来初始化您在堆栈上分配的项目。类似的原则也适用于析构函数。

    13. 大多数人认为Hungarian notation 的可读性与书面匈牙利语差不多。例外情况是讲匈牙利语的母语人士,他们通常会发现匈牙利符号与Cuneiform. 一样清晰易读。不幸的是,匈牙利符号在 Windows 软件中广泛使用,整个 Win32 API 都使用它,这对在该平台上编写的软件的易读性产生了预期的影响。

    14. C/Unix 书籍,即使是像已故 W Richard Stevens 所写的那些非常好的书籍,也往往可以通过亚马逊市场以相当便宜的价格买到二手书。没有特别的顺序,获取K&R,StevensAPUE和UNP 1& 2,Dragon book,Rochkind,Programming Pearls,Programming Pearls,Petzold和Richter(如果在Windows上工作)和任何其他经典的 C/Unix 作品。阅读,用铅笔在上面涂鸦,并通常与书籍互动。

    15. 网络上有很多很多好的C/Unix programming资源。

    16. 阅读并理解Ten Commandments of C Programming 以及关于戒律背后的原因和原因的一些元讨论。这在一定程度上显示了它的年龄,尽管其中大部分仍然相关并且晦涩的编译器仍然是quite common in the embedded systems world。

    17. 如果您想编写解析器,Lex and Yacc 是您的朋友。

    18. 作为 Navicore points out below (+1),Hanson 的 'C Interfaces and Implementations' 是一个针对模块化架构的接口/实现设计的失败案例,其中包含大量示例。我实际上听说过这本书,也听说过它的好消息,尽管我不能声称自己读过它。除了我上面描述的 C 习语之外,这个概念可以说是良好程序设计的核心。事实上,Modula-2 等其他过程语言实际上在其设计中明确了这一概念。这可能是最接近正在印刷的“C 程序架构”一书的内容。

    19. 阅读C FAQ。

    【讨论】:

    • 这些绝对是一些很好的要点。我很惊讶地看到 setjmp 和 longjmp 被如此突出地提及。虽然功能强大,但这两者的使用应该很少见,不是吗?如果您认为滥用 goto 是不好的(大多数人似乎如此),想象一下滥用 setjmp 和 longjmp(哎呀!)。至于汇编,我要补充一点,重要的是不仅要涉足编写自己的程序集,还要分析 C 编译器生成的程序集以了解实际情况。
    • Setjmp 比 goto 做得更多。它消除了函数的本地上下文。您通常会使用它来构建通用错误处理程序来代替结构化异常机制。建议是了解这种机制的工作原理。
    • 在 C 中没有像在 Java 中那样的例外,使用 goto 来实现类似的东西是正确的做法。
    【解决方案4】:

    David Hanson 的“C 接口和实现”解决了我从 OO 回到 C 的担忧。

    C Interfaces and Implementations

    说真的,它的方法在避免意外构建许多非 oo 系统最终形成的大纱线球方面产生了巨大的影响。

    【讨论】:

    • +1 - 感谢您提醒我。我听说过这本书,但我从未读过。接口/实现是一种关键的程序方法,在 Modula-2 中明确说明。将在我的帖子中指出这一点,因为我认为这可能是我听过的最接近“C 架构”的书。好想法 99 ;-}
    【解决方案5】:

    虽然它被写成与语言无关的文本,但Code Complete 提供了很多关于代码结构和组织以及构建实践的良好指导。

    【讨论】:

      【解决方案6】:

      更大的应用程序? C 的优势在于您必须处理设备驱动程序、调度程序和其他 OS 风格的东西等低级事物。

      您可以使 C 像 OO 一样运行,但这最终感觉就像是在重新发明轮子的练习..

      【讨论】:

      • 那些可能是相当大的应用程序,例如我知道 Linux 内核是用 C 编写的,但我本质上是在询问有关如何构建 C 程序的技术的信息,一旦你超过 500线。我知道很多人似乎误读了这个问题并认为我想在 C 中使用 OO,但我实际上对所有可用于构建大型 C 程序的技术感兴趣。
      • 哦,好吧,一种常见的方法是尝试将应用程序划分为模块,然后将每个模块分配给一个 .c 文件,在头 (.h) 文件中“宣传”其优点,然后然后使用#includes 来解决源依赖关系。在几个 KLOC 下工作得很好。当依赖关系失控,.h 文件开始包含其他 .h 文件,或者需要多个源目录,或者最终的恐怖,有人开始将变量声明放在 .h 文件中时,事情通常都是梨形的。
      【解决方案7】:

      一件小事是将你的 .c 文件“向后”排序 - 即将 main() 放在文件的底部,并始终确保本地函数(不在你的 .h 文件中的那些,你只是为在该文件中使用而编写的)位于它们首次使用的位置上方。这意味着您不必为它们编写原型,如果您必须更改它们的 API,这是一件少有的事情。

      然后,作为奖励,vim 中的 'gD' 命令将始终转到函数的定义,如果它在同一个文件中:)

      【讨论】:

      • 除了必须保持原型和主体同步之外,在 .c 文件开头的一个漂亮的原型块是内容的方便文档。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-25
      • 1970-01-01
      • 2011-07-02
      • 2015-11-03
      • 2011-05-19
      • 2010-11-27
      • 2011-09-19
      相关资源
      最近更新 更多