20

在下个月开始系统编程之前,我正在研究学习 C 基础知识和语法。在阅读时,我遇到了 C89/99 标准。根据维基百科,

C99 引入了几个新特性,包括内联函数、几个新数据类型(包括 long long int 和表示复数的复杂类型)、可变长度数组、支持可变参数宏(variadic macros of variable arity)和支持单行以 // 开头的注释,如在 BCPL 或 C++ 中。其中许多已经在几个 C 编译器中作为扩展实现。

C99 在很大程度上向后兼容 C90,但在某些方面更严格;特别是,缺少类型说明符的声明不再隐式假定为 int。使用值 199901L 定义标准宏 STDC_VERSION以指示 C99 支持可用。GCC、Sun Studio 和其他编译器现在支持 C99 的许多或全部新特性。

我借了一份 K&R,第 2 版,它使用 C89 标准。对于学生来说,使用 C89 是否会使 K&R 涵盖的某些科目无效,如果是,我应该注意什么?

4

8 回答 8

19

没有理由在 C99 上学习 C89 或 C90 - 它已被完全取代。很容易找到 C99 编译器,而且没有任何理由学习更早的标准。

这并不意味着您的教授不会强迫您使用 C89。从这里发布的标记为作业的各种问题中,我感觉到自 C89 以来,许多 C(不幸的是,C++)课程还没有继续。

从初学者的角度来看,您可能不会真正注意到差异 - 有很多 C 是 C99 和 C89/90 需要涵盖。

于 2010-12-05T13:35:20.270 回答
11

使用 C99 标准,它更新并具有更多功能。特别有用的可能是bool类型 in<stdbool.h>int32_tetc. 系列类型;后者防止了许多依赖于int具有一定大小的 s 的不可移植代码。AFAIK,它不会使 K&R 无效,尽管现在一些示例程序可能会以稍微不同的风格编写。

请注意,一些编译器仍然不能正确支持 C99。我相信 GCC 仍然需要使用一个-std=c99标志来启用它;许多 Unix/Linux 系统都有一个c99包装 GCC 并启用 C99 的命令。

许多大学教授也是如此。我交出一个在我大一时使用的程序让我感到惊讶bool。他从未听说过 C 语言中的那种类型 :)

于 2010-12-05T13:35:46.927 回答
4

虽然我一般同意其他人的观点,但值得注意的是,K&R 是一本非常好的书,值得从中学习 C,然后在阅读 C99 标准时更新你的知识。

于 2010-12-05T13:38:12.603 回答
3

如果您处于学生级别,您可能甚至不会注意到差异。

于 2010-12-05T13:42:03.573 回答
2

是的,有点奇怪的是,你可以得到一个响亮的共识,即 K&R 是一本伟大的 C 书,并且还有一个响亮的共识,即 C99 是 C 的正确/当前/最佳版本。这两个位置是不相容的——即使 K&R 是最好的书可以学习“C含义C99”,这只是意味着其余的都是垃圾,或者也已经过时了。

我建议学习和使用 C99,但在这样做时请留意 C89。如果您使用同时具有 C89 和 C99 兼容模式的编译器,那么您可以编写 C89 的一些位来了解差异。然后,如果您需要编写一些旨在移植到 C99 不去的地方的代码,您就会知道该怎么做。如果您永远不必编写任何此类代码,那么您可能已经浪费了一天。

正确编写 C89 实际上非常困难,因为获得 C89 标准的副本是很困难的。所以,如果可以的话,C99,如果出于某种奇怪的原因你必须这样做,C89,并且知道有什么区别。也许使用 K&R 来涵盖非常基础的内容,但请尽快查看一些惯用的 C99。

至于阅读 K&R 时需要注意的具体问题:标准前言中有一个重大变化列表(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf ),虽然细节没有在那里列出。其中很多是 C99 中添加的新功能,所以这并不是说 K&R错了,它可能并不总是为给定的工作使用最好的工具。其中一些是相当繁琐的事情,如果您仍然需要详细信息,您可能应该查阅标准。其余的是从 C89 中删除的内容,通常 C99 编译器会告诉您何时以及何时尝试使用它们。

于 2010-12-05T16:00:36.923 回答
1

作为学生,这对你影响不大。但如果可能的话,你应该找到一本涵盖 C99 的新 C 书籍

于 2010-12-05T13:37:27.493 回答
1

虽然我认为了解哪些功能较新且不太可能被晦涩(或故意破坏,如 MSVC)编译器支持是有益的,但您绝对应该使用一些 C99 功能:

  • snprintf:这是 C 中安全和干净的字符串汇编的最终功能。如果您的编译器缺少它,您可以替换整个printf子系统(可能是一个好主意,因为大多数缺少snprintf的实现也充满(通常是故意的)printf行为错误) ,或换行tmpfile/// fprintffreadfclose

  • stdint.h:如果您需要固定大小的类型(16/32/64 位),请使用标准名称int16_tuint16_tint32_t等。不要发明自己的名称,绝对不要使用特定于系统的名称,例如INT64or u32。它只会让你的代码变得丑陋并且难以集成和重用。如果您的编译器丢失stdint.h,只需插入您自己的编译器,以根据正确的平台类型定义类型。

  • 具体来说uint64_t,代替int foo[2];struct { int lo, int hi; } foo;或其他可怕的遗留黑客来处理 64 位数字。即使没有 C99 支持,任何健全的编译器都有自己的 64 位类型,您可以使用它来定义int64_tuint64_t.

于 2010-12-05T17:09:26.123 回答
1

术语“C89”描述了两种截然不同的语言:

  1. 程序员在 1989 年认为委员会在标准模棱两可的地方描述的语言,并且支持预先存在的实现中常见的功能。

  2. 委员会此后决定它想要描述的语言,这将与现有功能的兼容性排除在外。

C99“澄清”了标准中模棱两可的部分,说它们意味着标准的解释方式会破坏现有代码的大部分,并且无法像以前在 C 中那样高效地执行许多任务1989 年。

对于许多应用程序而言,正确的编程语言将是标准 C、C89、C99 和 C11 的超集。然而,重要的是,任何使用该语言编程的人都清楚他们正在使用该语言,而不是一个缩小的子集,它有利于速度而不是可靠性。

于 2011-03-15T15:23:34.713 回答