for循环中计数器变量的范围是啥?
Posted
技术标签:
【中文标题】for循环中计数器变量的范围是啥?【英文标题】:What is the scope of the counter variable in a for loop?for循环中计数器变量的范围是什么? 【发布时间】:2011-03-26 12:03:16 【问题描述】:我在 Visual Studio 2008 中收到以下错误:
Error 1 A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else
这是我的代码:
for (int i = 0; i < 3; i++)
string str = "";
int i = 0; // scope error
string str = ""; // no scope error
我知道一旦循环终止,str
将不复存在,但我也认为i
的范围也仅限于for
循环。
所以i
与在for
循环之外声明的变量具有相同的范围?
编辑:
为了清楚起见,我使用的是 C#。我正在讨论删除“C”标签。但是,由于正确答案解释了两者之间的区别,我认为留下两个标签是有意义的。
我在上面的代码注释中有一个错误:
for (int i = 0; i < 3; i++)
string str = "";
int i = 0; // scope error
string str = ""; // also scope error,
// because it's equivalent to declaring
// string str =""; before the for loop (see below)
【问题讨论】:
你已经标记了这个 c# 和 c。你问的是哪种语言?答案可能会有所不同,具体取决于您所指的语言。 请参阅***.com/questions/2693138/… 了解相同的问题,Eric Lippert 给出了很好的回答。另见***.com/questions/1196941/… 和***.com/questions/2059210/… 为了清楚起见,标记c#
和c
(或c++
)没有问题,如果您开始使用 我在 C# 3.0 中收到以下错误(Visual Studio 2008)... 和更高版本 for-loop 范围的 C# 规则与 ANSI C 有何不同?,这似乎是您的本意。但是您没有在原始问题中的任何地方指定您使用的是什么语言,在这种情况下,大多数人都会查看标签......这就是两个语言标签的问题所在。
【参考方案1】:
我认为你们都混淆了 C++ 和 C#。
在 C++ 中,过去在 for 表达式中声明的变量的范围在其后面的块之外。这在前段时间被改变了,因此在 for 表达式中声明的变量的范围在它后面的块的内部。 C# 遵循后一种方法。但两者都与此无关。
这里发生的情况是,C# 不允许一个作用域在外部作用域中隐藏同名的变量。
因此,在 C++ 中,这曾经是非法的。现在是合法的。
for (int i; ; )
for (int i; ; )
同样的事情在 C# 中也是合法的。共有三个作用域,未定义“i”的外部作用域和两个子作用域,每个作用域都声明了自己的“i”。
但你正在做的是:
int i;
for (int i; ; )
这里有两个作用域。一个外部声明一个“i”,一个内部声明一个“i”。这在 C++ 中是合法的 - 外部的 'i' 是隐藏的 - 但在 C# 中是非法的,无论内部范围是 for 循环、while 循环还是其他。
试试这个:
int i;
while (true)
int i;
同样的问题。 C# 不允许在嵌套范围内具有相同名称的变量。
【讨论】:
这个是正确答案。 C# 不允许您隐藏变量,因为它可能会造成混淆。 C++ 不在乎。它与for
循环语法,或者变量是在函数的顶部还是底部声明,或其他任何东西无关...
我发现实际阅读错误信息有时会有所帮助。【参考方案2】:
for循环后增量器不存在。
for (int i = 0; i < 10; i++)
int b = i; // this complains i doesn't exist
int i = 0; // this complains i would change a child scope version because the for's is a child scope of current scope
你不能在 for 循环之后重新声明 i 的原因是因为在 IL 中它实际上会在 for 循环之前声明它,因为声明发生在范围的顶部。
【讨论】:
+1 Hoffa:我猜你已经猜到了,但你为什么要删除你的示例代码?这是一个很好的观点。 @JohnB:我错误地声明了错误,现在已修复。有时只需要考虑这些事情:) @JohnB:请说明您使用的是什么语言。 @Luca Matteis:C#,但我认为这无关紧要! Hoffa 还指出变量声明的顺序是可逆的,这是一个好点,但 Jeff Dege 给出了真正的答案。【参考方案3】:是的。语法上:新的作用域在花括号定义的块内。功能上:在某些情况下,您可能需要检查循环变量的最终值(例如,如果您中断了)。
【讨论】:
+1 对,在 内,这完全有道理,并且保持一致!【参考方案4】:只是一些背景信息:序列没有涉及。只有范围的概念——方法范围和for
循环的范围。因此,“一旦循环终止”是不准确的。
因此,您发布的内容与此相同:
int i = 0; // scope error
string str = ""; // no scope error
for (int i = 0; i < 3; i++)
string str = "";
我发现这样思考会让答案更“适合”我的心智模型。
【讨论】:
+1 谢谢,很好!这样就更清楚了! (但没有直接回答我的问题,所以你没有得到支票)str
的双重声明在 C++ 中很好,但在 C# 中是范围错误。 OP 问题中的问题不在于在 same 范围内声明两个变量,而是 C# 不允许您在 nested 范围内拥有相同的变量,因为它可以令人困惑。 C++ 让你做令人困惑的事情。
约翰,当然,但你说什么让我的回答不恰当或没有帮助(假设你投票给我)?正如我所说,这是一些背景信息,正如 OP 所说,'谢谢,很好!这样就更清楚了”。
两个str
变量do 导致C# 中的错误,就像两个i
变量一样。两者都不会导致 C++ 中的错误。您的代码 sn-p 在任何一种语言中都是错误的。我并不是要继续说下去,但我认为您的回答增加了 OP 的困惑,而不是清除它。
@John Kugelman:最初说string str = ""; // no scope error
是我的错。但是,Kieren 确实明确了为什么我首先得到错误(这是因为该序列对于编译器是可逆的)。但是,我将支票交给 Jeff Dege,因为他提供了更明确的答案。以上是关于for循环中计数器变量的范围是啥?的主要内容,如果未能解决你的问题,请参考以下文章