ANSI C与其他C标准的区别

33
在我使用的几个编译器(全部是gcc,但版本不同)中,如果我在for循环表达式中而不是之前声明int i之后,则会收到类似于声明C99模式错误的提示(如果我没有使用std=c99选项)。从这里读取后,我了解到gcc选项-ansi、-std=c89和-std=iso9899:1990都等同于ANSI C标准,但我不明白为什么/是否应该选择c89标准而不是像c99这样的更新标准(我认为c99是最新的)。 此外,我看到有多个版本的C语言iso类型标准,其中第一个版本(据我的理解)是ANSI标准的直接移植。可以说,iso将会更新C的标准,但原始的ANSI C标准将永远不变吗? 额外问题: 我实际上可以自己找出答案,只是我还没有抽出时间去做,所以如果有人能够脱口而出那就太好了,否则也没关系,我以后会自己找出答案的 :)
我有一本相当新的《C程序设计语言(ANSI)》印刷版。 我的书总是像这样显示for循环:
int i;

for(i = 0; i < foo; i++)

但很多人(其中大多数人的编程技能比他们的小指还要强)会像这样编写他们的for循环:

(int i = 0; i < foo; i++)

如果我使用第一种方式编写循环,i 将会在整个函数中都可以访问,但如果我使用第二种方式,则无论我使用什么标准编译,i 只能在 for 循环内部访问。换句话说,如果我使用 c89 标准编译,两个 for 循环中的 i 都可以在整个函数中访问,如果我使用 c99 标准编译,第一个 for 循环中的 i 可以在整个函数中访问,而第二个 for 循环中的 i 只能在 for 循环内部访问。


1
你为什么说大多数人编写的循环都是那样的呢?根据C89标准,这显然是无效的。 - Carl Norum
8
我从未看过有人像那样用 C 语言编写循环。我自己也从来不这样做,因为我通常利用循环的副作用(使用变量 i 的最终值来确定循环何时结束以及原因)。 - R.. GitHub STOP HELPING ICE
2
@typoking:我更担心的是实际上支持所有C99的编译器非常少。在大多数情况下,C99并不是为了修复C89中的错误,而是为了向语言添加功能。 - James McNellis
2
@typoking:如果你说的是在技术勘误中纠正的错误,那就不用管它们了。在所有情况下,当人们谈论C89时,他们指的是修正之后的版本,而不是ANSI在1989年实际发布的文件。gcc和任何其他最新的编译器都应该包含TCs,尽管检查文档也没有坏处。 - Steve Jessop
"c99(我认为是最新的)" - 这是错误的,实际上还有c11 - el.pescado - нет войне
显示剩余12条评论
4个回答

22

C语言被ANSI标准化为C89。然后ISO将其标准化为C90;C89和C90之间没有技术差异。

C99是C标准的修订版;它由ISO C委员会开发,并由ISO和ANSI标准化。C89和C99都是ANSI标准。在常用语中,“ANSI C”一词通常指C89;K&R第2版书籍仅涵盖C89,而不包括C99。

为什么要选择使用旧版本的C?至少有两个原因。首先,您可能有一个不支持C99的编译器(例如,Microsoft Visual C++仅支持C89)。其次,存在大量遗留代码使用了C89中不允许在C99中使用的内容(您可以在问题“C99 backward compatibility”中查看更多信息;该问题还链接到描述差异的C99理论文档)。

至于“奖励问题”,在C89中无法在for语句中声明变量;但在C99中可以。在C89中,for语句的第一部分是表达式。


感谢你的回答,它确实帮助我更好地理解了这个问题。但是,我必须把胜利归功于Steve Jessop,他对'C89'被称为'ANSI'进行了详细的解释和澄清,并指出这只是一个“历史性的意外”。 - ubiquibacon

22
我不理解为什么/是否应该选择c89标准而不是像c99这样的更新标准(我认为这是最新的)。
原因有以下两点:
1)gcc对C99的支持并不完整,而它对C89的支持是。这就是为什么C89(带GNU扩展)是默认值。所以如果你是一个使用gcc编程标准的绝对坚定者,那么就选择C89。
2)Microsoft的编译器根本不支持C99。因此,如果您想编写可移植的C代码,C89是一种常见的标准。
"可以说iso将更新C的标准,但原始的ANSI C标准将永远不会改变吗?"
不,ISO C99也被批准为ANSI标准。将“ansi”这个名称附加到C89上只是一个不幸的历史事件。话虽如此,C89将永远是C89,它只不过不是最新的ANSI C标准而已。
"是否可以说,如果我用第一种方式编写循环,则i应该对整个函数都可访问,但如果我用第二种方式编写循环,则i仅对for循环可访问,而无论我使用哪种标准编译?"
在C89中,您无法以第二种方式编写循环(即使用-pedantic遵循标准),因此不存在“无论使用哪种标准”的情况。带GNU扩展的C版本不是标准,而是“方言”(至少man页面是这么称呼它们的)。在C89中,第二个循环是不合法的,在C99中,第二个循环将i的作用域限制在循环内。显然,在这两种情况下,第一个循环都给了i更广泛的作用域。
实际上,即使启用GNU扩展,gcc也不喜欢C89中的第二个循环。

3
啊,知道GNU扩展是"方言"而不是标准的事情真是太好了。 - ubiquibacon
1
微软编译器现在支持C99 :) - Étienne
@Étienne:你有这方面的来源吗?我知道微软一直在添加一些C99功能,但我没有意识到他们已经宣布完整(甚至是实质性的完整)支持。 - Steve Jessop
1
@SteveJessop他们不支持所有的东西,但是相当多:http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx - Étienne

3

我没有对C标准进行深入的解释。

但是,我的默认立场是在有机会的情况下使用C99。它是最新开发的标准之一,这是一个原因(我有一种错误的“更新就是更好”的感觉)。

主要原因是我可以在for循环中声明变量。

C99有效:

for (int i = 0; i < 100; i++)
{
   doSomething();
}

C89、ANSI和旧版:

int i;
for (i = 0; i < 100; i++)
{
   doSomething();
}

1

gcc的C99实现尚未完成,但在日常程序员生活中相当可用。我手头没有参考资料,但对于gcc来说,有一个声明声称他们将在这个实现被认为已经终止的那一天转向C99(或仅仅是他们的方言gnu99)。

使用C99特性与否的问题分为实用部分:

  • 我需要为哪些平台编译我的代码
  • 我会获得哪些功能(对我来说,很多清洁和易于编写可移植代码的特性)

还有情感/意识形态方面。对于后者,唯一的解决方法就是应用恐龙原则。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接