代码之家  ›  专栏  ›  技术社区  ›  KeatsPeeks

在你已经知道C++的时候学习C?

c c++
  •  18
  • KeatsPeeks  · 技术社区  · 16 年前

    我想我有一个高级的C++知识,我想学习C。

    有很多资源可以帮助人们从C到C++,但是我没有发现任何有用的东西来做相反的事情。

    明确地:

    1. 是否有广泛使用的通用程序库,每一个C程序员都应该知道(比如C++的Boost)?
    2. 什么是最重要的C习语(比如C++的RAII)?
    3. 我应该学习并使用C99,还是坚持使用C89?
    4. C++开发人员的陷阱/陷阱?
    5. 还有什么需要知道的吗?
    10 回复  |  直到 12 年前
        1
  •  26
  •   quark    16 年前

    这里已经有很多了,所以也许这只是一个小的补充,但这是我发现的最大的区别。

    图书馆:

    • 我把这放在第一位,因为在我看来,这是实践中最大的区别。C标准库非常(!)稀疏的它提供最少的服务。对于其他的事情,你必须自己翻滚或者找到一个图书馆来使用(很多人都这样做)。您有文件I/O和一些非常基本的字符串函数和数学。对于其他的事情,你必须自己滚动或找到一个图书馆来使用。我发现在从C++到C的时候,我错过了扩展的容器(特别是地图),但是还有很多其他的。

    习语:

    • 两种语言都有手动内存(资源)管理,但是C++提供了一些隐藏需求的工具。在C语言中,你会发现自己更经常用手跟踪资源,你必须习惯这一点。具体的例子是数组和字符串(C++) vector string 省去你很多工作),智能指针(你不能真的像在C中那样做“智能指针”。 可以 做引用计数,但是你必须自己上下引用,这是非常容易出错的——首先是智能指针被添加到C++中的原因,以及RAIE的缺乏,如果你习惯了C++编程的现代风格,你通常会注意到它无处不在。
      • 你必须对建筑和破坏有明确的认识。你可以争论这个缺陷的优点,但结果是有很多更明确的代码。
    • 错误处理。C++异常可能是棘手的,所以不是每个人都使用它们,但是如果你使用它们,你会发现你必须非常注意你如何做错误通知。需要检查所有重要调用的返回值(有些人会争辩 全部的 调用)需要大量的规则,而大量的C代码却不能做到这一点。
    • 字符串(和数组通常)不携带它们的大小。为了处理这个问题,您必须在C中传递许多额外的参数。
    • 如果没有名称空间,则必须小心地管理全局名称空间。
      • 函数和类型之间没有明确的联系 class 在C++中。您必须保持一个惯例,即预先固定与类型相关联的所有内容。
    • 你会看到更多的宏。宏在C语言中使用,在许多地方,C++具有相同的语言特性,尤其是符号常量(C)。 enum 但是很多旧的代码使用 #define 相反,以及泛型(其中C++使用模板)。

    忠告:

    • 考虑查找一个扩展库以供一般使用。看一看 GLib APR .
      • 即使您不想要一个完整的库,也可以考虑查找一个映射/字典/哈希表以供一般使用。还可以考虑捆绑包含大小的裸骨“字符串”类型。
    • 习惯于在所有公共名称上加上模块或“class”前缀。这有点乏味,但会减轻你的头痛。
    • 大量使用forward声明使类型不透明。在C++中,在头文件中可能有私有数据并依赖于 private 正在阻止访问,在C中,您希望尽可能将实现细节推送到源文件中。(在我看来,你实际上也希望在C++中这样做,但是C使它更容易,所以更多的人这样做。)

      C++显示了报头中的实现,尽管它在技术上隐藏了从类外部访问的实现。

      // C.hh
      class C
      {
          public:
             void   method1();
             int    method2();
      
         private:
             int    value1;
             char * value2;
      };
      

      C将“class”定义推送到源文件中。头是所有正向声明。

      // C.h
      typedef struct C C;           // forward declaration
      
      void c_method1(C *);
      int  c_method2(C *);
      
      // C.c
      struct C
      {
          int    value1;
          char * value2;
      };   
      
        2
  •  12
  •   scotchi    16 年前

    Glib 是现代C的一个很好的起点,它使您习惯了不透明类型和半对象方向等概念,这些概念在现代C中很常见。在光谱的另一端,标准POSIX API是一种“经典”C。

    从C++到C最大的差距不是语法,它是习语,在那里,像C++一样,有不同的编程流派。如果您使用的是设备驱动程序,而不是XML解析器,那么您将编写相当不同的C。

        3
  •  6
  •   Andrew O'Reilly    16 年前

    Q5。还有什么需要知道的吗?

    购买一份K&R2并阅读。从每页的成本来看,这本书可能是你用自己的钱买的最昂贵的计算机书籍,但它会让你对C和它的思维过程有深刻的理解。做练习也会磨练你的技能,让你习惯于语言中与C++无关的东西。

        4
  •  4
  •   Jerry Coffin    16 年前

    按顺序回答问题:

    1. 不幸的是,没有什么比C更强大的了。
    2. 没有什么是真正的RAII命令。
    3. 唯一试图实现c99的编译器是comeau。
    4. 恐怕到处都是。
    5. 相当多。C的思维方式与C完全不同。

    其中有些似乎相当简洁,但生活就是这样。C有一些很好的库,但是没有一个地方像他们收集到的Boost一样,或者没有一个像Boost这样的相对统一的接口。

    有很多成语,但其中很多都是关于如何编辑代码的,比如通过编写 fopen() 和一个匹配 fclose() 在快速连续的过程中,只在随后的两段时间内编写代码来处理数据。

    在每个角落等待的陷阱/陷阱大多源于缺少动态数据结构(如字符串和向量),因此您经常需要自己编写这样的东西。如果不使用运算符重载、构造函数等,则很难使它们真正具有通用性。很多图书馆都有它们,但你最终还是会卷起你自己的,因为:

    1. 图书馆做不到你想要的,或者
    2. 使用图书馆比它的价值更大。

    至少对我来说,心态上的差异几乎肯定是最大的。当我编写C++时,我几乎把所有的实际精力集中在设计最干净的可能的接口上,并且我倾向于将接口的实现视为 几乎 一次性代码。在大多数情况下,我并不打算对代码的这一部分做细微的调整——只要接口是好的,替换整个实现通常就足够容易,我不太担心。

    在C中,几乎完全或干净地将接口与实现分离似乎(至少在我看来)要困难得多。因此,我倾向于花费更多的时间来尽可能干净地实现代码的每一部分,因为以后的更改往往更困难,丢弃和替换不太好的部分的可能性要小得多。

    编辑(因为人们对C99支持提出了疑问):虽然我关于缺少C99支持的声明可能看起来很苛刻,但事实是这是真的。

    VC++:支持C95,并有一对夫妇的C99特性(例如C++风格的注释分隔符),主要是因为C99标准化了它们以前的扩展。

    GNU:根据 C99 Features Status page,最新的gcc(4.4)迭代有一些c99特性,但是一些(包括vlas)被描述为“坏的”,其他的则被描述为“丢失的”。一些缺失的“功能”实际上是完整的 地区 ,而不是单个功能。

    PCC: PCC site 声称C99合规性只是作为未来的目标,而不是作为现在的现实。

    Embarcadero Technologies(Nee Borland)似乎根本没有提到与C99的一致性——从表面上看,他们上一次使用C编译器可能早于C99发布。

    微软 openly states 他们目前没有支持C99的计划,而且在2010年的Vs发布之前,他们甚至不会考虑这一点。虽然我找不到任何公开声明,但Embarcadero似乎是一样的:没有当前计划的任何暗示,甚至他们也不会考虑很快就着手实施。

    虽然GCC和PCC似乎都有计划,但它们目前只是计划而已。他们都公开承认,目前,他们甚至不太接近符合C99。

        5
  •  2
  •   Dean J    16 年前

    这是一个 quick reference 一些你想知道的重要事情。

        6
  •  2
  •   Carl Smotricz    16 年前

    这是一个你没有要求的建议:我认为大多数潜在的雇主都认为,如果你知道C++,C.学习C的细点,而有趣的学术练习,IMO不会为你赢得很多资格。

    如果你最终处于一个需要做C的位置,你会很快地抓住这些差异。

    但别听我说。我太懒了,太笨了,不能学C++。

        7
  •  2
  •   vitaly.v.ch    16 年前

    还有什么需要知道的吗?

    C99不是C++的子集,而是单独的语言。

        8
  •  1
  •   Igor Zevaka    16 年前

    当我回到C时,我最大的震惊是变量是在函数级别定义的,也就是说,你不能在一个块中定义变量。( if 语句或 for 循环)在函数内部。

        9
  •  1
  •   Petruza    16 年前

    除了极少数情况下,任何C代码都是有效的C++,所以实际上没有任何新的东西你应该学习。
    这更像是一个不燃烧的问题。
    不使用新的、不使用类、在代码块开头定义变量等。
    严格意义上讲,C++不是面向对象的,但它仍然是支持类的过程。也就是说,你实际上已经在C++中使用了程序化编程,最令人震惊的改变是没有类、继承、多态等。

        10
  •  0
  •   anon    16 年前

    因为C++几乎是C89的超集,所以你应该已经知道了所有的C89。你可能想把注意力集中在C89和C99之间的区别上。