为嵌套循环声明虚拟变量的更好方法是什么?
Which is the better way to declare dummy variables for nested loops?
方法 1 的优点是文件大小稍小,因为源代码中的文本字符较少:
int i, j;
for (i = 0; i < numRows; i++)
for (j = 0; j < numCols; j++)
//<some code here>
方式二的优点是局部变量作用域较小
int i;
for (i = 0; i < numRows; i++)
{
int j;
for (j = 0; j < numCols; j++)
//<some code here>
}
即使在当今的现代计算机中优化的差异可以忽略不计,哪种方法被认为是 "better" 代码?
编辑以澄清此问题不是重复的:
此题基于当前的 C11 标准,该标准不允许这样的语法:
for (int i = 0; i < numRows; i++)
在 C++ 和 C99 中,这种语法是完全可以接受的,而 C11 不允许在 for
语句中声明变量。
编辑更正错误信息:
我以为我使用的是 C11,因为我最近从 CodeBlocks 下载了编译器,所以这就是为什么我说 C11 不允许在 for
语句中声明变量。但事实证明我实际上使用的是 C90,这是我问题的根源。
第二种方法是最好的方法
- 可以使用低内存
- 允许在任何其他循环中需要时再次使用同一变量
为了纯粹的紧凑性和范围的限制,我会使用:
for (size_t i = 0; i < numRows; i++) {
for (size_t j = 0; j < numCols; j++) {
//<some code here>
}
}
请注意,size_t
的使用似乎是数组索引。 size_t
类型是 unsigned
整数类型,保证能够保存任何数组索引。只是风格问题,但我还建议在所有循环体周围使用大括号。这使得您不太可能因不可避免的更新和更改而破坏您的代码。
通过养成这样声明具有块作用域的循环变量的习惯,您可以强迫自己选择在代码的其他地方使用存储在循环变量中的值。
这似乎是一个品味问题,没有任何确定的答案,但我会告诉你我的看法:
以目前的计算机,保存几个字符的源代码简直微不足道。事实上,我想即使我在 1976 年在 VAX 11/780 上学习 C 时也会这么说。
我更喜欢第二个例子,因为目前的偏好是声明变量尽可能接近第一次使用。在 C++ 中,您甚至可以将循环变量的声明放在 for 语句中:
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
...
}
}
但这仍然只是个人喜好问题:相信如果变量的声明接近于使用,程序将更具可读性。
这两种方法都不是首选。
两个常见的编码指南是 (1) 确保没有变量存在的时间超过它需要的时间,以及 (2) 不要将一个变量用于不止一件事。遵循此类准则可以减少(通常但并非总是消除)以非预期方式意外使用变量,因此有助于避免细微的编程错误。
在您的第一种情况下,i
和 j
都将继续存在,直到封闭范围结束 - 这意味着它们在循环完成后仍然存在。这最大限度地增加了后续代码(在该封闭范围内)意外重用 i
或 j
用于另一个目的的机会(例如,当意图是使用另一个变量时)。这样的错误通常很难找到。
第二种情况也有同样的问题,除了i
。不过,即使一个变量出现这样的问题也是个坏消息。
我可能会使用像
这样的结构
// unintentionally using i or j here will cause a compilation error
for (int i = 0; i < numRows; i++)
{
// unintentionally using j here will cause a compilation error
for (int j = 0; j < numCols; j++)
{
//<some code here>
}
// unintentionally using j here will cause a compilation error
}
// unintentionally using i or j here will cause a compilation error
(我为说明这一点而插入的注释使它更难读,但在实践中通常不需要这样的注释)。
这确保了 i
和 j
都不存在于外循环之外。这也意味着 j
不能在外循环中意外使用。实际上,当需要输入 j
时很容易输入 i
(反之亦然)——例如,它们在 QWERTY 键盘上靠得很近。 i
和 j
在视觉上看起来也很相似,所以视觉代码检查经常会错过这样的错误。但是,使用这样的方法,编译器将检测到此类拼写错误。如果可以选择,最好让编译器找出错误,而不是让人类费力地找到错误。
当然,这并不能阻止 i
和 j
在内部循环中的误用或互换 - 但这是指南通常鼓励使用比 [=11 更多信息的名称的原因之一=] 和 j
- 滥用视觉上不同的名称更容易被普通人发现。
方法 1 的优点是文件大小稍小,因为源代码中的文本字符较少:
int i, j; for (i = 0; i < numRows; i++) for (j = 0; j < numCols; j++) //<some code here>
方式二的优点是局部变量作用域较小
int i; for (i = 0; i < numRows; i++) { int j; for (j = 0; j < numCols; j++) //<some code here> }
即使在当今的现代计算机中优化的差异可以忽略不计,哪种方法被认为是 "better" 代码?
编辑以澄清此问题不是重复的:
此题基于当前的 C11 标准,该标准不允许这样的语法:
for (int i = 0; i < numRows; i++)
在 C++ 和 C99 中,这种语法是完全可以接受的,而 C11 不允许在 for
语句中声明变量。
编辑更正错误信息:
我以为我使用的是 C11,因为我最近从 CodeBlocks 下载了编译器,所以这就是为什么我说 C11 不允许在 for
语句中声明变量。但事实证明我实际上使用的是 C90,这是我问题的根源。
第二种方法是最好的方法
- 可以使用低内存
- 允许在任何其他循环中需要时再次使用同一变量
为了纯粹的紧凑性和范围的限制,我会使用:
for (size_t i = 0; i < numRows; i++) {
for (size_t j = 0; j < numCols; j++) {
//<some code here>
}
}
请注意,size_t
的使用似乎是数组索引。 size_t
类型是 unsigned
整数类型,保证能够保存任何数组索引。只是风格问题,但我还建议在所有循环体周围使用大括号。这使得您不太可能因不可避免的更新和更改而破坏您的代码。
通过养成这样声明具有块作用域的循环变量的习惯,您可以强迫自己选择在代码的其他地方使用存储在循环变量中的值。
这似乎是一个品味问题,没有任何确定的答案,但我会告诉你我的看法:
以目前的计算机,保存几个字符的源代码简直微不足道。事实上,我想即使我在 1976 年在 VAX 11/780 上学习 C 时也会这么说。
我更喜欢第二个例子,因为目前的偏好是声明变量尽可能接近第一次使用。在 C++ 中,您甚至可以将循环变量的声明放在 for 语句中:
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
...
}
}
但这仍然只是个人喜好问题:相信如果变量的声明接近于使用,程序将更具可读性。
这两种方法都不是首选。
两个常见的编码指南是 (1) 确保没有变量存在的时间超过它需要的时间,以及 (2) 不要将一个变量用于不止一件事。遵循此类准则可以减少(通常但并非总是消除)以非预期方式意外使用变量,因此有助于避免细微的编程错误。
在您的第一种情况下,i
和 j
都将继续存在,直到封闭范围结束 - 这意味着它们在循环完成后仍然存在。这最大限度地增加了后续代码(在该封闭范围内)意外重用 i
或 j
用于另一个目的的机会(例如,当意图是使用另一个变量时)。这样的错误通常很难找到。
第二种情况也有同样的问题,除了i
。不过,即使一个变量出现这样的问题也是个坏消息。
我可能会使用像
这样的结构// unintentionally using i or j here will cause a compilation error
for (int i = 0; i < numRows; i++)
{
// unintentionally using j here will cause a compilation error
for (int j = 0; j < numCols; j++)
{
//<some code here>
}
// unintentionally using j here will cause a compilation error
}
// unintentionally using i or j here will cause a compilation error
(我为说明这一点而插入的注释使它更难读,但在实践中通常不需要这样的注释)。
这确保了 i
和 j
都不存在于外循环之外。这也意味着 j
不能在外循环中意外使用。实际上,当需要输入 j
时很容易输入 i
(反之亦然)——例如,它们在 QWERTY 键盘上靠得很近。 i
和 j
在视觉上看起来也很相似,所以视觉代码检查经常会错过这样的错误。但是,使用这样的方法,编译器将检测到此类拼写错误。如果可以选择,最好让编译器找出错误,而不是让人类费力地找到错误。
当然,这并不能阻止 i
和 j
在内部循环中的误用或互换 - 但这是指南通常鼓励使用比 [=11 更多信息的名称的原因之一=] 和 j
- 滥用视觉上不同的名称更容易被普通人发现。