我注意到C11不再允许你在循环结构中声明迭代器变量,例如,以下是无效的:
for (int i = 0; i < 10; ++i)
但这是可以的:
int i;
for (i = 0; i < 10; ++i)
考虑到在C99之前,除了在函数(块)的开头之外,甚至不可能声明变量。C11是否允许在函数中的任何位置声明变量?),我很好奇这与安全实践有什么关系。迭代器应该在它们所在的函数或块的顶部声明,还是在使用它们的第一个循环的上方声明?我看不出这两种方法有什么区别,但是前一种方法在移动代码时似乎更健壮。就安全而言,我看不出有什么明显的影响。
另外,C11中上述变化的首要原因是什么?我比较喜欢第一个示例中的语法。
编辑:对于我的最后一个问题,我认为一个问题是,如果迭代器被多次使用,在块内移动for (int i = 0; ...
将不容易重构。
你怎么会有这个想法?
C11草案第6.8.5(1)节说:
迭代语句:
, (表达式)声明
声明 , (表达式);
(表达式<子>选择子>;<<em>表达式/em> <子>选择子>;<<em>表达式/em> <子>选择 ) 声明子>
(声明表达式<子>选择子>;<<em>表达式/em> <子>选择 ) 声明子>
最后一种形式很清楚地表明,在for
语句的第一个子句中仍然允许声明。
注意声明类似于int i = 0 ;
。也就是说,它包含分号(参见6.7节)。所以for (int i = 0 ; i < 10 ; ++i)
是C11所允许的。
至于什么时候用哪个,那是一个意见问题。我的意见是,你应该尽可能嵌入声明,因为它使代码更容易阅读。
如果我正在阅读你的代码,我看到:
for (int i = 0 ; i < 10 ; ++i)
...
…那么我就知道你在循环结束后没有依赖i
的值,因为它不再在作用域中了。
如果我看到:
int i;
for (i = 0 ; i < 10 ; ++i)
...
…然后我希望你稍后使用i
的值;例如,也许你早break
,想知道i
发生时是什么。如果我以后没有看到你使用i
,我可能会想知道你在想什么和/或我错过了什么。
根据你链接的问题,C11应该仍然允许你在for循环中声明变量(为什么他们会像那样破坏向后兼容性?)。
在任何情况下,如果你是编译C89(由微软编译器支持的C标准),那么你只能在一个块的开始声明新的变量(即::右括号)。好消息是,您可以在任何地方放置新块,而不仅仅是在函数的顶部,因此您可以通过将其包装在一组额外的花括号中来模拟C99 for循环作用域:
/* ... */
{int i; for(i=0; i<10; i++){
/* ... */
}}
/* ... */