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

“便携”C是否应该编译为C++?

  •  18
  • unwind  · 技术社区  · 15 年前

    我得到一个评论 an answer 我发布了一个C问题,评论家建议代码应该用C++编译器编写,因为最初提到的代码应该是“可移植的”。

    这是“便携式C”的常见解释吗?正如我在对该答案的进一步评论中所说,我完全感到惊讶,我认为可移植性意味着完全不同的东西,并且在编写C代码也是合法C++的过程中看到的好处很少。

    11 回复  |  直到 12 年前
        1
  •  16
  •   Community CDub    7 年前

    不,我的反应 Why artificially limit your code to C? 有一些符合标准的C99的例子没有编译为C++;较早的C没有什么差异,但是C++有更强的类型和不同的处理方法。 (void) 函数参数列表。

    至于C’便携到C++的好处是什么——在这个答案中引用的一个特定的项目是一个基于特征的语言的虚拟机,所以它不适合C++对象模型,并且有很多情况下你正在拉。 void* 解释器的堆栈,然后转换为表示内置对象类型布局的结构。为了使代码“便携”到C++,它会添加很多类型的转换,这对于类型安全来说毫无用处。

        2
  •  18
  •   DevSolar    12 年前

    目前的C++(1998)标准采用了C(1989)标准。一些关于类型安全的精细打印放在一边,这意味着“好”C89应该在C++编译器中编译得很好。

    问题是现行的C标准是1999(C99)的标准,即 然而,正式的一部分的C++标准(AFAIK)(*)。这意味着C99的许多“更好”的特性(long long int,stdint.h,…),而 支持 通过许多C++编译器, 严格遵守。

    “可移植的”C完全意味着别的东西,与官方的ISO/ANSI标准几乎没有关系。这意味着您的代码不会对主机环境做出假设。(int、endianes、非标准函数或errno数字的大小,诸如此类。)

    我曾经为一个跨平台项目写过一本编码风格指南:

    跨平台DNA(不要假设)

    • 没有本机数据类型。您可以使用的唯一数据类型是那些在标准库中声明的数据类型。
    • char、short、int和long的大小各不相同,就像float、double和long double一样。
    • int不是32位。
    • char既不是有符号的也不是无符号的。
    • char不能包含数字,只能包含字符。
    • 将短类型转换为长类型(int->long)会破坏CPU的对齐规则。
    • int和int*的大小不同。
    • int*和long*的大小不同(指向任何其他数据类型的指针也是如此)。
    • 您还记得本地数据类型甚至不存在吗?
    • “A”-“A”的结果与“Z”-“Z”的结果不同。
    • “Z”-“A”的结果与“Z”-“A”的结果不同,并且不等于25。
    • 除了测试空指针的值之外,不能对其执行任何操作;取消对空指针的引用将使系统崩溃。
    • 涉及有符号和无符号类型的算术不起作用。
    • 数据类型的对齐规则随机更改。
    • 数据类型的内部布局随机更改。
    • 过流和下流的具体行为是随机变化的。
    • 函数调用abis随机更改。
    • 操作数按随机顺序计算。
    • 只有编译器才能解决这种随机性。随机性将随着CPU/OS/编译器的下一个版本而改变。
    • 对于指针,==和!=仅适用于指向完全相同数据类型的指针。
    • <,>仅适用于同一数组中的指针。它们只适用于char显式声明的unsigned。
    • 您还记得本机数据类型不存在吗?
    • 大小t(size of返回值的类型)不能转换为任何其他数据类型。
    • ptrdiff_t(从另一个指针中减去一个指针的返回值的类型)不能转换为任何其他数据类型。
    • wchar_t(宽字符的类型,其确切性质是实现定义的)不能转换为任何其他数据类型。
    • 任何…\t数据类型不能转换为任何其他数据类型

    (*) 这在写作的时候是真的。事情在C++ 11中有了一些变化,但是我的答案的要点是正确的。

        3
  •  8
  •   Simon Nickerson    15 年前

    可移植性意味着编写代码,以便使用不同的编译器和/或不同的平台(即,尽可能依赖于ISO标准规定的行为)编译和具有相同的行为。

    让它使用另一种语言的编译器进行编译是一种很好的方法(也许),但我不认为这就是可移植性的含义。由于C++和C现在越来越分散,这将很难实现。

    另一方面,在编写C代码时,我仍然避免使用“class”作为标识符。

        4
  •  3
  •   tpdi    15 年前

    不,“便携”并不意味着“编译在C++编译器上”,它意味着“编译任何标准的SealMunt C编译器”,具有一致的、定义的行为。

    而且不要剥夺自己,比如说,C99改进只是为了保持C++的兼容性。

    但是,只要保持兼容性不束缚你的手,如果你能避免使用“类”和“虚拟”之类的东西,那就更好了。如果你正在编写开源程序,有人可能想把你的代码移植到C++中;如果你想租用,你的公司/客户可能会在将来某个时间去港口。嘿,也许将来你甚至想把它移植到C++

    做一个“好管家”,不要在营火周围乱扔垃圾,这只是你做任何事情的好业力。

    请不要让不兼容的内容出现在你的邮件头中。即使你的代码从来没有移植过,人们可能需要从C++链接到它,所以有一个不使用任何C++保留字的标题是很酷的。

        5
  •  2
  •   Chris Lutz    15 年前

    视情况而定。如果你正在做一些可能对C++用户有用的东西,那么它可能是个好主意。如果你正在做C++用户永远不需要的东西,但是C用户可能觉得方便,不要费心让C++兼容。

    如果你正在编写一个程序来做很多人做的事情,你可以考虑让它尽可能广泛地使用。如果你正在写一个Linux内核的添加,你可以把C++的兼容性放在窗口——这是不需要的。

    试着猜猜谁可能会使用你的代码,如果你认为很多C++迷可能觉得你的代码有用,那就考虑一下C++吧。但是,如果你认为大多数C++程序员都不需要它(即C++中已经相当标准化的一个特性),不用麻烦了。

        6
  •  2
  •   trshiv    15 年前

    使用C++编译器编译C代码是为了进行更严格的类型检查,这是一种常见的做法。尽管有类似于LICT的C专用工具,但是使用C++编译器更方便。

    使用C++编译器编译C代码意味着你通常必须用ExtN“C”块包围你的包,以告诉编译器不要损坏函数名。但是,这不是合法的C语法。实际上,你使用的是C++语法,而你的代码,实际上是C,实际上是C++。此外,使用“C++便利”的趋势也开始像使用未命名的联盟一样蠕动。

    如果需要严格保持代码C,则需要小心。

        7
  •  2
  •   none    15 年前

    FWW,一旦一个项目获得了一定的规模和势头,它实际上不可能从C++兼容性中获益:即使它不会直接移植到C++,也确实存在。 许多的 与工作/处理相关的现代工具C++源代码。

    在这个意义上,缺乏与C++的兼容性,实际上可能意味着你可能需要拿出自己的工具来做具体的事情。我完全理解在某些平台、环境和项目上支持C在C++之上的推理,但C++兼容性通常从长远来看简化了项目设计,最重要的是: 它提供了选项 .

    此外,还有许多C项目最终会变得如此庞大,以至于它们实际上可能受益于C++的能力,例如使用抽象的改进支持和使用具有访问修饰符的类的封装。

    以Linux(内核)或GCC项目为例,这两个项目基本上都是“C”,但在开发者社区中经常有关于切换到C++的潜在收益的讨论。

    事实上,海湾合作委员会目前正在努力( 在里面 FSF树!将GCC源导入有效的C++语法(参见: gcc-in-cxx 详细说明),因此可以使用C++编译器编译源代码。

    这基本上是由一个长期的海湾合作委员会黑客:伊恩兰斯泰勒发起的。

    最初,这仅仅是为了提供更好的错误检查,以及改进的兼容性(即一旦完成这一步骤,这意味着您不必有一个C编译器来编译GCC,您也可以只使用一个C++编译器,如果你恰巧是‘C++开发者’,那就是你所得到的。

    但最终,这个分支的目的是鼓励向C++迁移。 实现语言 对GCC来说,这是一个真正革命性的步骤——一个被金融稳定基金的人批判的范式转变。

    另一方面,很明显,GCC已经受到其内部结构的严重限制,任何至少有助于改善这种情况的东西都应该受到赞扬:开始为GCC项目做出贡献是不必要的复杂和乏味,主要是由于内部结构复杂,已经开始进行仿真。C++中使用宏和GCC特定扩展的许多高级功能。

    准备最终切换到C++的GCC代码库是最合乎逻辑的事情(不管它实际上是在什么时候完成的)!为了保持竞争性、趣味性和简单明了,这实际上是必需的。 相关的 这尤其适用于非常有前途的工作,如LLVM,它不会带来所有这些困难和复杂性。

    虽然用C编写非常复杂的软件通常是可能的,但这样做会变得不必要的复杂,许多项目在很长一段时间前就已经完全不再使用C了。这并不意味着C不再相关,相反。但是考虑到一定的代码基础和复杂性,C不一定是理想的工作工具。

    事实上,你甚至可以说C++对于某些项目来说不一定是理想的语言,但是只要语言本身支持封装并提供执行这些抽象的手段,人们就可以绕过这些限制。

    仅仅因为很明显可以用非常低级的语言编写非常复杂的软件,并不意味着我们必须这样做,或者说它在第一时间确实是有效的。

    我在这里谈论的是具有数十万行代码的复杂软件,其使用寿命长达几十年。在这种情况下,选择越来越重要。

        8
  •  2
  •   Patrick Schlüter    15 年前

    不,不管味道如何。 我不喜欢抛出空指针,为了不多的好处而混乱代码。

    char * p = (char *)malloc(100);
    

    VS

    char * p = malloc(100);
    

    当我写一个“面向对象”的C库模块时,我真的很喜欢用“这个”作为我的对象指针,因为它是一个C++关键字,它不会在C++中编译(它是故意的,因为这些模块在C++中是毫无意义的,因为它们在STL和库中确实存在)。

        9
  •  1
  •   anon    15 年前

    你为什么看不到什么好处?这很容易做到,谁知道将来您将如何使用代码。

        10
  •  1
  •   Andy Dent    15 年前

    不,可编译的C++不是便携式的常见解释。处理真正的旧代码,K&AM.R风格声明是高度可移植的,但不能在C++下编译。

    如前所述,您可能希望使用C99增强功能。不过,我建议您考虑所有目标用户,确保他们可以使用这些增强功能。不要只使用可变长度的数组等,因为你有自由,但只有在真正合理的情况下。

    是的,尽可能多地保持C++兼容性是一件好事——其他人可能有一个很好的理由需要编译C代码作为C++。例如,如果他们想要将它包含在一个MFC应用程序中,他们必须在一个单独的dll或库中构建纯C,而不仅仅是能够将代码包含在一个项目中。

    还有一个论点,即在C++模式下运行编译器可能会遇到微妙的错误,这取决于编译器,如果应用不同的优化。

        11
  •  1
  •   techcraver    15 年前

    所有经典代码中的C编程语言,第二版都可以使用标准的C++编译器,如GCC(G++)编译。如果你的C代码符合经典文本中的标准,那么就足够好了,你已经准备好用C++编译器编译C代码了。

    以Linux内核源代码为例,它主要是用C语言编写的,有一些内嵌汇编代码,这是一个恶梦,用C++编译器编译Linux内核代码,因为在Linux内核代码中使用“新”作为变量名的可能性最小,因为C++不允许使用“新”作为变量名。我只是举一个例子。请记住,Linux内核是可移植的,它在Intel、PPC、SPARC等体系结构中运行良好。这只是为了说明可移植性在软件世界中有着不同的含义。如果您想用C++编译器编译C代码,则将代码库从C迁移到C++。我认为它是两种不同的编程语言,最明显的原因是C程序员不太喜欢C++。但我喜欢这两种类型,而且我经常使用这两种类型。你的C代码是可移植的,但是你应该确保你遵循标准的技术,让你的C++代码移植,同时你的C代码迁移到C++代码。继续阅读,看看从哪里可以获得标准技术。

    你必须非常小心地把C代码移植到C++代码中,接下来我要问的是,如果一些C代码是便携的,并且没有问题地运行,为什么你会麻烦这么做呢?我不能接受可管理性,Linux内核——C语言中的一个大代码源——的管理也很好。

    总是将两种编程语言C++C++视为不同的编程语言,尽管C++支持C&它的基本概念是始终支持这种奇妙的语言,用于向后兼容。如果你不把这两种语言看成是不同的工具,那么你就陷入了流行的、丑陋的C/C++编程语言战争的境地。

    选择可移植性时使用以下规则:

    a)您的代码(C或C++)需要在不同的体系结构上编译,可能使用本机C/C++编译器吗? b)研究不同的体系结构的C/C++编译器,希望运行程序和代码移植计划。在这上面花点时间。 C)尽可能地在C代码和C++代码之间提供一个干净的分离层。如果你的C代码是可移植的,你只需要用可移植的C++编码技术再次在C++的C代码上写C++包装。

    翻到一些不错的C++书籍,关于如何编写便携C++代码。我个人推荐Bjarne Stroustrup自己的C++编程语言,来自史葛迈尔斯和流行的DDJ文章的有效C++系列,在www. DDJ.com。

    PS: Linux内核示例在我的文章中只是为了说明,便携性在软件编程中意味着不同的含义,并且不批评Linux内核是用C&编写的,而不是C++。