17

我习惯了老式的 C 并且最近才开始探索 c99 的特性。我只有一个问题:如果我在我的程序中使用 c99、c99 标志gcc并将它与以前的 c99 库链接,我的程序会成功编译吗?

那么,我应该坚持旧的 C89 还是进化?

4

8 回答 8

11

我相信它们在这方面是兼容的。只要您正在编译的东西没有踩到​​任何新的好东西。例如,如果旧代码包含,enum bool { false, true };那么你就有麻烦了。作为一只相似的恐龙,我正在慢慢拥抱C99的精彩新世界。毕竟,它现在只潜伏了大约 10 年;)

于 2009-11-16T02:01:37.783 回答
8

你应该进化。感谢收听 :-)

实际上,我将对此进行扩展。

没错,C99 已经存在了很长一段时间。您应该(在我看来)将该标准用于遗留代码以外的任何内容(您只需修复错误而不是添加新功能)。遗留代码可能不值得,但您应该(与所有业务决策一样)进行自己的成本/收益分析。

我已经确保我的新代码与 C1x 兼容——虽然我还没有使用任何新功能,但我尝试确保它不会损坏。

至于要注意哪些代码,标准的作者非常重视向后兼容性。他们的工作从来不是设计一种新语言,而是编纂现有的实践。

他们目前所处的阶段允许他们在更新语言方面有更大的自由度,但他们在输出方面仍然遵循希波克拉底誓言:“首先,不要伤害”。

通常,如果您的代码被新标准破坏,编译器会被迫告诉您。所以简单地编译你的代码库将是一个很好的开始。但是,如果您阅读C99 基本原理文档,您会看到“安静的变化”一词出现 - 这是您需要注意的。

这些是编译器中的行为变化,您不需要被告知,如果您的应用程序开始表现得很奇怪,它们可能会引起很多焦虑和咬牙切齿。不要担心“c89 中的安静变化”位 - 如果它们是一个问题,那么您已经被它们咬了。

顺便说一句,该文档是一本很好的读物,可以理解为什么实际的标准会这么说。

于 2009-11-16T02:37:09.093 回答
3

某些 C89 功能不是有效的 C99

可以说,这些特性的存在只是出于历史原因,不应在现代 C89 代码中使用,但它们确实存在。

C99 N1256 标准草案前言第 5 段将 C99 与旧版本进行了比较,并且是开始搜索这些不兼容性的好地方,尽管它的扩展远多于限制。

隐式 int 返回和变量类型

Lutz 在评论中提到,例如以下是有效的 C89:

static i;
f() { return 1; }

但不是 C99,您必须在其中编写:

static int i;
int f() { return 1; }

这也排除了在 C99 中调用没有原型的函数:C89、C90 或 C99 中的所有函数都需要原型吗?

n1256 说:

删除隐式 int

不带表达式返回非 void 函数

有效 C89,无效 C99:

int f() { return; }

我认为在 C89 中它返回一个实现定义的值。n1256 说:

在返回值的函数中不允许不带表达式的返回

带负操作数的整数除法

  • C89:四舍五入到实现定义的方向
  • C99:四舍五入为 0

因此,如果您的编译器四舍五入-inf,并且您依赖于该实现定义的行为,那么您的编译器现在被迫在 C99 上破坏您的代码。

https://stackoverflow.com/a/3604984/895245

n1256 说:

可靠的整数除法

Windows 兼容性

一个主要的实际问题是能否在 Windows 中编译,因为 Microsoft不打算过早完全实施 C99

这就是为什么 libgit2限制允许 C99 功能的原因。

于 2015-05-13T07:16:44.913 回答
2

恭敬地:试一试,找出答案。:-)

不过,请记住,即使您需要修复一些细微的编译差异,向上移动也可能是值得的。

于 2009-11-16T02:16:42.550 回答
2

如果您不违反明确的 C99 功能,则 c90 代码将与另一个先前的 c99 库一起正常工作 c99 标志。

但是在 C89 中有一些基于 dos 的库,比如,,那肯定行不通。

C99 非常灵活,因此可以随意迁移 :-)

于 2009-11-16T02:26:51.657 回答
2

C 库之间的调用约定多年来没有改变,事实上,我不确定它是否曾经改变过。

此时的操作系统严重依赖 C 调用约定,因为 C API 往往是操作系统各部分之间的粘合剂。

所以,基本上答案是“是的,二进制文件将向后兼容。不,当然,使用 C99 功能的代码以后不能用非 C99 编译器编译。”

于 2009-11-16T02:35:29.300 回答
1

它旨在向后兼容。它使许多供应商已经实施的扩展形式化。使用 C99 编译时,编写良好的程序可能不会有任何问题,甚至可能。

以我的经验,重新编译一些模块而不是其他模块以节省时间......浪费了大量时间。通常有一些容易被忽视的细节需要新的编译器来兼容。

于 2009-11-16T02:13:12.677 回答
1

C89 标准的一些部分写得模棱两可,根据人们如何解释关于指针类型和它们正在访问的对象的规则,该标准可能被视为描述两种截然不同的语言之一——一种其中一个在语义上更强大,因此可用于更广泛的领域,其中之一允许更多基于编译器的优化机会。C99 标准“澄清”了该规则,以明确表明它没有努力强制要求与前一种语言兼容,尽管它在许多领域都受到压倒性的支持;它还将 C89 中定义的某些事物视为未定义,但这只是因为 C89 规则的编写不够精确以禁止它们(例如,使用memcpy在目标具有堆持续时间的情况下用于类型双关语)。

因此,C99 可能与其作者认为由 C89 描述的语言兼容,但与整个 1990 年代大多数 C89 编译器处理的语言不兼容。

于 2016-09-09T17:45:57.833 回答