【问题标题】:Compiling C code using multiple compilers使用多个编译器编译 C 代码
【发布时间】:2014-09-29 03:46:51
【问题描述】:

我最近刚决定学习 C。我注意到我可以下载多个编译器。如果我为一个编译器编写 C 代码,它应该适用于所有编译器,对吗?

【问题讨论】:

  • 使用尽可能多的不同编译器编译代码是一个好主意(N > 1 比 N == 1 好得多)。您将对代码的问题有不同的看法。确保您还将编译器上的警告级别调高,然后注意他们所说的话。例如,如果其中一个编译器是 GCC,您可以使用 -Wall -Wextra -Werror 来发现大部分问题。您还可以指定一个标准,例如-std=c11,并可能添加-pedantic 以避免意外使用编译器扩展。我使用的选项比 GCC 更多。
  • 让多个编译器保持最新状态并为每个编译器构建大量库(您自己的和第三方的)等可能有点痛苦。值得看看像 cmake 这样的工具,它可以通过多个编译器。这不是一个神奇的为您完成一切的解决方案,但它可以提供帮助。几年前,我经常在 MinGW GCC 和 VC++ 之间来回切换。即使只使用 GCC,我仍然使用 cmake。

标签: c windows compilation


【解决方案1】:

简短回答:是的

长答案:

是的,但前提是(且不限于):

  • 您的代码未使用其他编译器不可用的编译器特定内容
  • 您的代码所依赖的库在其他编译器上可用并正确设置
  • 您的代码不会调用/依赖未定义或实现定义的行为
  • 其他编译器大致使用与当前编译器相同的 C 标准进行编译。

当我想到它们时,我会在列表中添加更多内容。

【讨论】:

  • 未定义行为是指一个编译器可以比另一个编译器更好地处理未定义行为?意味着一个编译器中的错误,而另一个编译器中的错误,对吗?
  • @user3155415 未定义的行为正是它所说的:未定义。这意味着两个不同的编译器可以做两件完全不同的事情。两者都不比另一个“更好”。未定义的行为始终是逻辑错误。
  • 实现定义的行为不一定是个大问题。例如,LONG_MAX 的值是实现定义的,因此如果您的代码根据LONG_MAX 的值更改它所做的事情,它就会显示实现定义的行为。但这可能根本不是问题。未定义的行为是有问题的行为,'nasal demons'——例如,“未定义的行为可能会让恶魔飞出你的鼻子”——应该令人难忘(如果不可信)。
  • 关于未定义行为 - 如果您有带有大量指针强制转换的旧式数据结构代码,则很容易出现未定义行为。具体来说,编译器可能不会发现两个指针实际上是同一个指针。此指针别名问题可能导致通过一个指针的引用无法看到通过另一个指针写入的更改。实际上,更新更好的编译器往往会发现错误——更复杂的优化往往会发现错误。在这种情况下,如果每次读/写都被强制到主内存,则别名指针不是(可见的)错误——它只是很慢。
【解决方案2】:

在 C 标准中定义了两种类型的 'compiler-dependent' 问题:

  • 实现定义的行为:行为可能因编译器而异,但编译器必须提供某种一致的行为,并且必须记录此行为。

    直接来自标准的示例:“实现定义行为的示例是当有符号整数右移时高位的传播。”。换句话说,-1 >> 1的结果可能因编译器而异,但编译器必须保持一致。

  • 未定义的行为:当您遇到未定义的行为时,任何事情 - 我的意思是任何事情都可能发生。

您还需要注意违反约束的情况。通常,该标准会指定诸如“[main] 应使用 int [...] 的返回类型定义”(第 5.1.2.2.1/1 节)之类的内容。这相当于,“如果 main 声明的返回类型不是 int,则程序的行为是未定义的。” (参见第 4.2 节,标准明确支持这种解释)

请注意,某些实现定义的行为有限制 - 例如,sizeof(int) 的值是实现定义的,但您知道 sizeof(int) >= sizeof(short) && sizeof(int) - 所以只要有任何实现定义的行为并不意味着你不能说出程序做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2014-01-16
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多