ANSI C 和 K&RC 之间的主要区别是什么?
ANSI C 标准化过程的目标之一是产生 K&RC(第一个发布的标准)的超集,其中包含随后引入的许多非官方功能。 然而,标准委员会还包括了一些新功能,例如函数原型(借用自 C++ 编程语言)和功能更强大的预处理器。 参数声明的语法也已更改以反映 C++ 风格。
这让我认为存在差异。 不过我没有看到K&RC和ANSI C的比较,有这样的文档吗? 如果不是,主要区别是什么?
编辑:我相信 K&R 书的封面上写着“ANSI C”。 至少我相信我家里的版本是这样的。 那么也许不再有区别了?
The Wikipedia article on ANSI C says:
One of the aims of the ANSI C standardization process was to produce a superset of K&R C (the first published standard), incorporating many of the unofficial features subsequently introduced. However, the standards committee also included several new features, such as function prototypes (borrowed from the C++ programming language), and a more capable preprocessor. The syntax for parameter declarations was also changed to reflect the C++ style.
That makes me think that there are differences. However, I didn't see a comparison between K&R C and ANSI C. Is there such a document? If not, what are the major differences?
EDIT: I believe the K&R book says "ANSI C" on the cover. At least I believe the version that I have at home does. So perhaps there isn't a difference anymore?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
这里对于“K&R C”是什么可能有些混淆。 该术语指的是《C 编程语言》第一版中记录的语言。 粗略地说:大约 1978 年贝尔实验室 C 编译器的输入语言。Kernighan
和 Ritchie 参与了 ANSI 标准化过程。 “ANSI C”方言取代了“K&R C”,并且“C 编程语言”的后续版本采用了 ANSI 约定。 “K&R C”是一种“死语言”,除非某些编译器仍然接受遗留代码。
There may be some confusion here about what "K&R C" is. The term refers to the language as documented in the first edition of "The C Programming Language." Roughly speaking: the input language of the Bell Labs C compiler circa 1978.
Kernighan and Ritchie were involved in the ANSI standardization process. The "ANSI C" dialect superceded "K&R C" and subsequent editions of "The C Programming Language" adopt the ANSI conventions. "K&R C" is a "dead language," except to the extent that some compilers still accept legacy code.
有一些细微的差异,但我认为 K&R 的更高版本适用于 ANSI C,因此不再有真正的差异。
由于缺乏更好的术语,“C Classic”定义函数的方式略有不同,即
我相信另一个区别是函数原型。 原型不必(事实上他们不能)采用参数或类型列表。 在 ANSI C 中是这样的。
There are some minor differences, but I think later editions of K&R are for ANSI C, so there's no real difference anymore.
"C Classic" for lack of a better terms had a slightly different way of defining functions, i.e.
I believe the other difference was function prototypes. Prototypes didn't have to - in fact they couldn't - take a list of arguments or types. In ANSI C they do.
功能原型是 K&RC 和 C89 之间最明显的变化,但还有很多其他变化。 C 库的标准化也投入了大量的重要工作。 尽管标准 C 库是现有实践的编纂,但它编纂了多个现有实践,这使得它变得更加困难。 PJ Plauger 的书标准 C 库是一个很好的参考,并且还讲述了为什么该库最终会变成这样的一些幕后细节。
ANSI/ISO 标准 C 在大多数方面与 K&RC 非常相似。 大多数现有的 C 代码应该基于 ANSI 编译器构建,而无需进行太多更改。 但至关重要的是,在标准之前的时代,语言的语义可以由每个编译器供应商解释。 ANSI C 引入了语言语义的通用描述,使所有编译器处于平等地位。 大约 20 年后的今天,人们很容易认为这是理所当然的,但这是一项重大成就。
在大多数情况下,如果您没有需要维护的预标准 C 代码库,您应该很高兴不必担心它。 如果你这样做了——或者更糟糕的是,如果你试图将一个旧程序提高到更现代的标准——那么我对你表示同情。
Function prototypes were the most obvious change between K&R C and C89, but there were plenty of others. A lot of important work went into standardizing the C library, too. Even though the standard C library was a codification of existing practice, it codified multiple existing practices, which made it more difficult. P.J. Plauger's book, The Standard C Library, is a great reference, and also tells some of the behind-the-scenes details of why the library ended up the way it did.
The ANSI/ISO standard C is very similar to K&R C in most ways. It was intended that most existing C code should build on ANSI compilers without many changes. Crucially, though, in the pre-standard era, the semantics of the language were open to interpretation by each compiler vendor. ANSI C brought in a common description of language semantics which put all the compilers on an equal footing. It's easy to take this for granted now, some 20 years later, but this was a significant achievement.
For the most part, if you don't have a pre-standard C codebase to maintain, you should be glad you don't have to worry about it. If you do--or worse yet, if you're trying to bring an old program up to more modern standards--then you have my sympathies.
另一个区别是函数返回类型和参数类型不需要定义。 它们将被假定为整数。
并且
是相同的。
Another difference is that function return types and parameter types did not need to be defined. They would be assumed to be ints.
and
are identical.
ANSI C 和 K&RC 之间的主要区别如下:
ANSI C 采用 C++ 函数原型技术,其中函数定义和声明包括函数名称、参数的数据类型和返回值数据类型。 函数原型使 ANSI C 编译器能够检查用户程序中传递无效参数数量或不兼容参数数据类型的函数调用。 这些修复了 K&RC 编译器的主要弱点。
示例:声明一个函数 foo 并要求 foo 采用两个参数
The major differences between ANSI C and K&R C are as follows:
ANSI C adopts c++ function prototype technique where function definition and declaration include function names,arguments' data types, and return value data types. Function prototype enable ANSI C compiler to check for function calls in user programs that pass invalid numbers of arguments or incompatible arguments data types. These fix major weakness of the K&R C compiler.
Example: to declares a function foo and requires that foo take two arguments
尽管有所有相反的说法,K&R 过去和现在都非常有能力提供从底层到硬件的任何类型的东西。
现在的问题是找到一个编译器(最好是免费的),它可以对几百万行 K&RC 进行干净的编译,而不必搞乱它。并且可以在 AMD 多核处理器之类的东西上运行。
据我所知,在查看了 GCC 4.xx 系列的源代码后,没有简单的方法可以将 -traditional 和 -cpp-traditional 滞后功能重新激活到之前的工作状态,而无需付出比我准备更多的努力从头开始构建 K&R pre-ansi 编译器更简单。
Despite all the claims to the contary K&R was and is quite capable of providing any sort of stuff from low down close to the hardware on up.
The problem now is to find a compiler (preferably free) that can give a clean compile on a couple of millions of lines of K&R C without out having to mess with it.And running on something like a AMD multi core processor.
As far as I can see, having looked at the source of the GCC 4.x.x series there is no simple hack to reactivate the -traditional and -cpp-traditional lag functionality to their previous working state without without more effor than I am prepered to put in. And simpler to build a K&R pre-ansi compiler from scratch.
我认为,最大的区别是函数原型和描述函数参数类型的语法。
The biggest single difference, I think, is function prototyping and the syntax for describing the types of function arguments.
区别在于:
The difference is:
尚未有人提及的一个主要区别是,在 ANSI 之前,C 很大程度上是根据先例而不是规范来定义的; 如果某些操作在某些平台上产生可预测的结果,但在其他平台上则不然(例如,在两个不相关的指针上使用关系运算符),先例强烈支持为程序员提供平台保证。 例如:
在定义指向所有对象的所有指针之间的自然排名的平台上,可以依赖对任意指针应用关系运算符来产生该排名。
在测试一个指针是否“大于”另一个指针的自然方法除了产生 true 或 false 值之外不会产生任何副作用的平台上,将关系运算符应用于任意指针同样可以依赖于永远不会除了产生 true 或 false 值之外,有任何副作用。
在
在整数溢出自然自动换行的补码平台上,涉及小于“int”的无符号值的操作在结果介于 INT_MAX+1u 和UINT_MAX 并且它没有提升为更大的类型,也没有用作
>>
的左操作数,也没有用作/
、%
的操作数> 或任何比较运算符。 顺便说一句,该标准的基本原理将此作为小型无符号类型升级为有符号的原因之一。在 C89 之前,尚不清楚上述假设自然不成立的平台的编译器可能会在多大程度上支持这些假设,但毫无疑问,可以轻松且廉价地支持此类假设的平台的编译器应该这样做。 C89 标准的作者没有费心明确地说出这一点,因为
该标准仅要求实现能够运行一个可能人为设计的程序而不会出现堆栈溢出,并认识到虽然迟钝的实现可以将任何其他程序视为调用未定义的行为,但认为不值得担心迟钝编译器编写者编写了“符合”但无用的实现。
尽管“C89”同时被解释为“C89 定义的语言,加上平台提供的任何附加功能和保证”,但 gcc 的作者一直在推动一种解释,排除超出 C89 规定的任何功能和保证。
A major difference nobody has yet mentioned is that before ANSI, C was defined largely by precedent rather than specification; in cases where certain operations would have predictable consequences on some platforms but not others (e.g. using relational operators on two unrelated pointers), precedent strongly favored making platform guarantees available to the programmer. For example:
On platforms which define a natural ranking among all pointers to all objects, application of the relational operators to arbitrary pointers could be relied upon to yield that ranking.
On platforms where the natural means of testing whether one pointer is "greater than" another never has any side-effect other than yielding a true or false value, application of the relational operators to arbitrary pointers could likewise be relied upon never to have any side-effects other than yielding a true or false value.
On platforms where two or more integer types shared the same size and representation, a pointer to any such integer type could be relied upon to read or write information of any other type with the same representation.
On two's-complement platforms where integer overflows naturally wrap silently, an operation involving an unsigned values smaller than "int" could be relied upon to behave as though the value was unsigned in cases where the result would be between INT_MAX+1u and UINT_MAX and it was not promoted to a larger type, nor used as the left operand of
>>
, nor either operand of/
,%
, or any comparison operator. Incidentally, the rationale for the Standard gives this as one of the reasons small unsigned types promote to signed.Prior to C89, it was unclear to what lengths compilers for platforms where the above assumptions wouldn't naturally hold might be expected to go to uphold those assumptions anyway, but there was little doubt that compilers for platforms which could easily and cheaply uphold such assumptions should do so. The authors of the C89 Standard didn't bother to expressly say that because:
Compilers whose writers weren't being deliberately obtuse would continue doing such things when practical without having to be told (the rationale given for promoting small unsigned values to signed strongly reinforces this view).
The Standard only required implementations to be capable of running one possibly-contrived program without a stack overflow, and recognized that while an obtuse implementation could treat any other program as invoking Undefined Behavior but didn't think it was worth worrying about obtuse compiler writers writing implementations that were "conforming" but useless.
Although "C89" was interpreted contemporaneously as meaning "the language defined by C89, plus whatever additional features and guarantees the platform provides", the authors of gcc have been pushing an interpretation which excludes any features and guarantees beyond those mandated by C89.