2014-05-09 26 views
1

我注意到,C11不再允许您在循环结构内声明的迭代变量,例如,以下是无效的:放置在C11(编码风格)

for (int i = 0; i < 10; ++i) 

但是,这是OK:

int i; 
for (i = 0; i < 10; ++i) 

鉴于C99之前甚至没有可能除了在功能(块?Does C11 allow variable declarations at any place in a function?)的开头声明变量,我很好奇,如何这涉及到安全的做法。迭代器是否应该在它们所在的函数或块的顶部声明,或者只是在第一个循环之上声明它们?我看不出任何方式都有很大的不同,但前一种方法似乎对移动代码更加稳健。就安全性而言,我没有看到任何明显的影响。

此外,C11上述变化的原因是什么?我非常喜欢第一个例子中的语法。

编辑:到我最后一个问题,我想有一个问题是,如果迭代器被多次使用,在一个块内移动for (int i = 0; ...将不那么容易重构。

+2

你使用的是'gcc -std = c11'。如果只使用'gcc'而不指定标准,则默认为'gnu89',它不允许在for循环中声明。在ANSI C,C89中就是这样的,但是限制被删除,同时“混合声明和代码” –

+0

我看到了,我没有使用该选项。 – bbarker

+0

我曾假设我至少使用c99,因为我可以使用stdbool.h。 – bbarker

回答

6

在哪里你有这个想法吗?

C11 draft,节6.8.5(1),说:

iteration-statement:

while (expression) statement

dostatementwhile (expression) ;

for (expressionopt ; expressionopt ; expressionopt) statement

for (declarationexpressionopt ; expressionopt) statement

这最后一种形式使得它很清楚,声明仍可以在for语句的第一个子句。

[更新]

注意声明是一样的东西int i = 0 ;。也就是说,它包含了分号(参见第6.7节)。因此C11肯定允许for (int i = 0 ; i < 10 ; ++i)

[更新2]

至于何时使用哪个,也就是见仁见智。我的意见是,你应该尽可能地嵌入声明,因为它使代码更易于阅读。

如果我读你的代码,我看到:

for (int i = 0 ; i < 10 ; ++i) 
... 

...然后我知道你是不是依靠i值循环结束后,因为它不再在范围内。

如果我看到:

int i; 
for (i = 0 ; i < 10 ; ++i) 
... 

...然后我希望你用的i后的价值;例如也许你早点break,想知道i是什么时候发生的。如果我以后没有看到你使用i,我可能会想知道你在想什么和/或我错过了什么。

像往常一样,可读性是最重要的指标。当然,符合“可读性”的是一个意见。

+0

奇怪的是,当我运行vanilla gcc命令(版本4.8.1 )与前者我得到''错误:'为循环初始声明只允许在C99模式' – bbarker

+1

工作一整天,每天在GCC和MSVC。但有一点需要注意。我的范围仅在{}循环内。一如既往,哪里使用哪种形式需要一些判断。 – RocketRoy

+1

@bbarker:总是告诉gcc你想编译的C方言。请参阅[这个问题](http://stackoverflow.com/questions/5060799/c99-not-default-c-version-for-gcc) – hugomg

2

根据你链接的问题,C11应该仍然允许你在for循环中声明变量(为什么它们会像这样反向兼容?)。在任何情况下,如果您正在编译针对C89(由Microsoft编译器支持的C标准),那么您只能在块的开头声明新变量(即:右大括号后)。好消息是,你可以把一个新的块anywere,不只是在函数的顶部,因此您可以通过它环绕一组额外的花括号内模拟C99 for循环范围:

/* ... */ 
{int i; for(i=0; i<10; i++){ 
    /* ... */ 
}} 
/* ... */