为什么在不同的编译器上编译C / C ++代码很重要?

时间:2009-12-31 18:52:11

标签: c++ c gcc compiler-construction portability

我 对可移植性的不同方面感兴趣(正如你在浏览我的其他问题时所看到的那样),所以我读了很多关于它的内容。很多时候,我读/听说Code应该以一种可以在不同编译器上编译的方式编写。

在gcc / g ++没有任何实际生活经验的情况下,在我看来它支持所有可以想象的主要平台,因此编译g ++的代码几乎可以在任何系统上运行。那么为什么有人会费心在MS编译器,英特尔编译器和其他人上运行他的代码呢?

我也可以想到一些原因。正如常见问题解答建议的那样,我会尝试将它们作为答案发布,反对将它们纳入我自己的问题中。

编辑:结论

你们让我完全相信有几个很好的理由支持多个编译器。原因很多,很难选择一个被接受的答案。对我来说最重要的原因是:

  • 贡献者更有可能使用我的项目,或者只要他们可以使用他们选择的编译器就可以使用它
  • 随处可编辑,可用于未来的编译器和工具,并遵守标准相互执行,所以这是一个好主意

另一方面,我仍然相信还有其他更重要的事情,现在我知道有时它根本不重要。

最后,没有一个单一的答案可以说服我不要选择GCC作为我项目的主要默认编译器。

13 个答案:

答案 0 :(得分:20)

从我的头脑中出现的一些原因:

1)避免被单个编译器供应商锁定(开源与否)。

2)使用不同编译器编译代码可能会发现更多错误:警告不同,不同的编译器在不同程度上支持标准。

答案 1 :(得分:13)

在MSVC上进行编译是件好事,因为有些人可能拥有他们想要将代码链接到的MSVC中构建的项目,而无需建立完全不同的构建系统。

在英特尔编译器下进行编译是件好事,因为它经常编译更快的代码。

Clang下进行编译是件好事,因为它可以提供更好的错误信息并提供更好的开发体验,并且它比GCC更容易进行工作,因此可能在未来获得额外的好处

通常,最好保持选项打开,因为没有一个编译器可以满足所有需求。 GCC是一个很好的编译器,对于大多数用途来说都很棒,但是你有时需要别的东西。

即使您通常只是在GCC下编译,确保您的代码在其他编译器下编译也可能有助于找到可能阻止您的代码与过去和未来版本的GCC一起工作的问题,例如,如果GCC现在不那么严格,但后来添加了检查,另一个编译器可能会提前捕获,帮助您保持代码清洁。在相反的情况下我发现这有用,其中GCC捕获的警告比MSVC更多的潜在问题(MSVC是我们需要支持的唯一编译器,因为我们只在Windows上发布,但我们做了部分端口到Mac在我们的空闲时间GCC下,这使我能够生成比其他方式更清晰的代码。

答案 2 :(得分:12)

可移植性。如果您希望可以通过尽可能多的人访问您的代码,则必须使其适用于最广泛的编译器。它与使网站在IE以外的浏览器上运行的想法相同。

其中一些是政治性的。公司有标准,人们有喜欢的工具等。告诉别人他们应该使用X,真的让一些人失望,并使其他人真的无法接触。

Nemanja也提出了一个很好的观点,针对某个编译器锁定您使用它。在开源世界中,这可能不是一个大问题(尽管人们可能会停止开发它并且它​​已经过时了),但是如果您购买它的公司停止产品或停业呢?

答案 3 :(得分:9)

对于大多数语言,我更少关注可移植性,而更多地关注符合国际标准或接受的语言定义,从而可能遵循属性可移植性。然而,对于C来说,可移植性是一个有用的想法,因为编写一个“严格符合”标准的程序非常困难。 (为什么?因为标准委员会认为有必要对一些现有的做法进行处理,包括给编译器一些你可能不喜欢的自由。)

那么为什么要尝试符合标准或让你的代码可以被多个编译器接受,而不是简单地编写gcc(或你喜欢的其他编译器)接受的任何东西?

  • 可能在2015年,gcc会接受一种与现在截然不同的语言。您不希望重写旧代码。

  • 也许您的代码可能被移植到非常小的设备上,而GNU工具链的支持不是很好。

  • 如果您的代码compiles with any ANSI C compiler straight out of the box with no errors and no warnings,您的用户的生活将更加轻松,您的软件可能会被广泛移植和使用。

  • 也许有人会发明一个很棒的新工具来分析C程序,重构C程序,提高C程序的性能,或者发现C程序中的错误。我们不确定该工具将使用哪个版本的C或它可能基于什么编译器,但几乎可以肯定该工具将接受标准C。

在所有这些论点中,这是我发现最有说服力的工具论点。人们忘记了除了编译和运行源代码之外,还可以使用源代码做其他事情。在另一种语言中,Haskell,用于分析和重构的工具远远落后于编译器,但坚持使用Haskell 98标准的人可以访问 lot 更多工具。类似的情况很可能是C:如果我要去构建一个工具的努力,我将基于一个生命周期为10年左右的标准,而不是可能在之前改变的gcc版本我的工具已经完成。

尽管如此,很多人都可以完全忽视可移植性。例如,在1995年,我努力说服Linus Torvalds使用任何ANSI C编译器编译Linux成为可能,而不仅仅是gcc。 Linus没有任何兴趣 - 我怀疑他得出的结论是他或他的项目中没有任何内容。而他是对的。让Linux编译只使用gcc对于编译器研究人员来说是一个很大的损失,但Linux没有损失。 “工具论证”并不适用于Linux,因为Linux变得如此受欢迎;为C程序构建分析和错误查找工具的人愿意使用gcc,因为在Linux上运行会使他们的工作产生重大影响。因此,如果你可以指望你的项目像Linux或Mosaic / Netscape一样成功,你可以忽略标准: - )

答案 4 :(得分:5)

如果您要为不同的平台构建,最终将使用不同的编译器。此外,C ++编译器往往略微落后于C ++标准,这意味着它们通常会随着时间的推移而改变对它的依从性。如果将目标分配给所有主要编译器,则代码维护成本会降低。

答案 5 :(得分:4)

其他开发人员希望使用不同编译器的应用程序(尤其是开源应用程序)非常常见。有些人宁愿将Visual Studio与MS Compiler一起用于开发目的。有些人宁愿使用英特尔编译器来声称性能优势等等。

答案 6 :(得分:4)

所以这就是我能想到的原因

  • 如果速度是最大的问题,并且某些平台有特殊的,高度优化的编译器
  • 如果您使用C ++接口构建库(类和模板,而不仅仅是函数)。由于名称修改和其他东西,库必须使用与客户端代码相同的编译器进行编译,如果客户端想要使用Visual C ++,他必须能够使用它编译lib
  • 如果你想支持一些没有gcc支持的非常罕见的平台

(对我来说,这些原因并不重要,因为我想在内部构建一个使用C ++的库,但是有一个C接口。)

答案 7 :(得分:4)

通常这些是我找到的原因:

  • 跨平台(windows,linux,mac)
  • 不同的开发人员在不同的操作系统上进行开发(虽然不是最佳的,但确实发生了 - 测试通常仅在目标平台上进行)。
  • 编译器公司破产 - 或停止使用该语言进行开发。如果您知道您的程序使用其他编译器编译/运行良好,那么您已经完成了投注。

我确信还有其他答案,但这些是我到目前为止遇到的最常见的原因。

答案 8 :(得分:4)

这是“有赖”的问题之一。对于开源代码,可以移植到多个编译器。毕竟让人们在不同的环境中构建代码是非常重要的。

但对于封闭源,这不是那么重要。您永远不希望不必要将自己绑定到特定的编译器。但是在我工作过的大多数地方,编译器的可移植性甚至没有成为我们关注的前十名。即使您从未使用过标准C / C ++以外的任何东西,将大型代码库切换到新的编译器也是一件危险的事情。编译器有bug。有时你的代码会在一个编译器上有一些良性的错误,但在另一个编译器上突然出现问题。

我记得有一个过渡,一个编译器认为这段代码很好:

for (int ii = 0; ii < n; ++ii) { /* some code */ }
for (int ii = 0; ii < y; ++ii) { /* some other code */ }

虽然较新的编译器抱怨ii已被声明两次,但我们必须遍历所有代码并在循环之前声明循环变量才能切换。

我工作的一个地方非常小心编译器开关的意外副作用,他们检查了每个源代码树中的特定编译器,并且一旦发出的代码只使用那个编译器对该代码库进行更新 - 永远。 / p>

另一个地方会在他们切换到它之前试用一个新的编译器6个月到一年。

答案 9 :(得分:4)

有几个项目使用GCC / G ++作为正常使用的“日常”编译器,但每隔一段时间都会检查以确保其代码遵循Comeau C/C++ compiler的标准。他们的网站看起来像是一场噩梦,编译器不是免费的,但它可能是最符合标准的编译器,并且会警告你许多编译器会默默地接受或明确允许作为非标准扩展的东西(是的,我我看着你,先生,我不介意 - 实际上 - 积极支持你的努力 - 指针算术 - 虚拟指针-GCC)。

使用与Comeau一样严格的编译器进行编译(或者更好的是,使用尽可能多的编译器进行编译)将让您了解人们在尝试编译代码时可能遇到的错误,事情你的编译器允许你不应该这样做,并且可能是其他编译器不允许你这样做的事情。编写ANSI C或C ++应该是您打算在多个平台上使用的代码的重要目标,并且使用最符合标准的编译器是一种很好的方法。

(免责声明:我没有Comeau,也没有计划得到它,因为我在OS X上而无法得到它。我做C而不是C ++,所以我实际上可以知道整个语言,平均C编译器比C ++标准的平均C ++编译器更接近C标准,所以对我来说这不是一个问题。只是想把它放在这里,因为这看起来像是一个Comeau的广告它应该被视为一个用于编译许多不同编译器的广告。)

答案 10 :(得分:2)

我发现gcc在Windows上是一个缓慢的编译器(没有什么可以在linux下进行比较)。所以我(有时)想在其他编译器下编译我的代码,只是为了加快开发周期。

答案 11 :(得分:2)

我认为到目前为止还没有人提到它,但另一个原因可能是访问某些特定于平台的功能:许多操作系统供应商都有特殊版本的GCC,甚至是他们自己的家 - 生成(或许可和修改)的编译器。因此,如果您希望代码在多个平台上运行良好,则可能需要在每个平台上选择正确的编译器。是嵌入式系统,MacOS,Windows等。

此外,速度可能是一个问题(编译速度和执行速度)。回到PPC时代,GCC在PowerPC CPU上产生了众所周知的慢速代码,因此Apple将一大批工程师放在GCC上进行改进(GCC对于Mac来说非常新,所有其他PowerPC平台都很小)。较少使用的平台可能在GCC中的优化程度较低,因此使用为该平台编写的另一个编译器可以更快。

但作为最后的总结:虽然在编译几个编译器时有理想的价值,但在实践中,这对于跨平台软件(和开源软件,主要是因为它通常可以相当快地跨平台进行,如果他们可以使用他们选择的编译器而不必学习新的编译器,那么贡献者就会更容易。如果您只需要在一个平台上发货, shipping 维护通常比投资构建多个编译器更重要,如果您只发布使用一个编译器构建的版本他们但是,您需要清楚地记录与标准(例如GCC-isms)的任何偏差,以便在您必须执行此操作时更轻松地移植。

答案 12 :(得分:1)

英特尔编译器和llvm都比gcc快。使用gcc的真正原因是

  • 无限的硬件支持(没有其他编译器可以在您的旧DEC上编译乐高头脑风暴代码。)

  • 便宜

  • 业务中最好的spagety优化器。