Какова область действия переменной счетчика в цикле for?

В 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)

person JohnB    schedule 06.08.2010    source источник
comment
Вы отметили это C # и c. О каком языке вы спрашиваете? Ответ может быть разным, в зависимости от того, какой язык вы имеете в виду.   -  person James McNellis    schedule 06.08.2010
comment
См. stackoverflow.com/questions/2693138/ на тот же вопрос с отличным ответом Эрика Липперта. Также см. stackoverflow.com/questions/1196941/ и stackoverflow.com/questions/2059210/   -  person jloubert    schedule 06.08.2010
comment
Для ясности: нет проблем с пометкой как c#, так и c (или c++), ЕСЛИ вы начали с , я получаю следующую ошибку в C # 3.0 (Visual Studio 2008) ... и более поздних версиях. Чем правила C # для области видимости цикла отличаются от ANSI C?, что, похоже, именно то, что вы планировали. Но вы не указали нигде в исходном вопросе, какой язык вы использовали, и в этом случае большинство людей смотрят на теги ... вот где возникает проблема с двумя языковыми тегами.   -  person Ben Voigt    schedule 07.08.2010


Ответы (4)


Я думаю, вы все путаете 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 # не допускает использование переменных с одинаковыми именами во вложенных областях.

person Jeff Dege    schedule 06.08.2010
comment
Это правильный ответ. C # не позволяет скрывать переменные, потому что это может сбивать с толку. С ++ все равно. Это не имеет ничего общего с синтаксисом цикла for, объявлением переменных вверху или внизу функции или чем-то еще ... - person John Kugelman; 06.08.2010
comment
Я обнаружил, что на самом деле чтение сообщения об ошибке иногда бывает полезным. - person Jeff Dege; 06.08.2010

После цикла 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

Причина, по которой вы не можете повторно объявить i после цикла for, заключается в том, что в IL он фактически объявляет его перед циклом for, потому что объявления происходят в верхней части области.

person Jimmy Hoffa    schedule 06.08.2010
comment
+1 Хоффа: Я думаю, вы уже догадались, но почему вы удалили образец кода? Это был отличный момент. - person JohnB; 06.08.2010
comment
@JohnB: Я неправильно заявлял об ошибке, сейчас исправлено. Иногда просто приходится продумывать эти вещи :) - person Jimmy Hoffa; 06.08.2010
comment
@JohnB: объясните, пожалуйста, на каком языке вы говорите. - person Luca Matteis; 06.08.2010
comment
@ Лука Маттеис: C #, но я не думал, что это имеет значение! - person JohnB; 07.08.2010
comment
Хоффа также отметил, что последовательность объявления переменных обратима, что является хорошим моментом, но у Джеффа Деге есть реальный ответ. - person JohnB; 07.08.2010

Да. Синтаксически: новая область видимости находится внутри блока, определенного фигурными строками. Функционально: бывают случаи, когда вы можете захотеть проверить окончательное значение переменной цикла (например, если вы сломались).

person Nicolas78    schedule 06.08.2010
comment
+1 правильно, внутри {}, это имеет смысл и делает его последовательным! - person JohnB; 06.08.2010

Просто некоторая справочная информация: последовательность не входит в это. Есть только представление об области действия - области метода, а затем области for цикла. Таким образом, «после завершения цикла» неточно.

Таким образом, ваше сообщение читается примерно так:

int i = 0; // scope error
string str = ""; // no scope error

for (int i = 0; i < 3; i++)
{
  string str = "";
}

Я считаю, что такие размышления об этом лучше подходят для моей ментальной модели.

person Kieren Johnstone    schedule 06.08.2010
comment
+1 Спасибо и отличный момент! Это еще лучше проясняет ситуацию! (но прямо не отвечает на мой вопрос, поэтому вы не получите чек) - person JohnB; 06.08.2010
comment
Двойное объявление str нормально в C ++, но это ошибка области видимости в C #. Проблема в вопросе OP заключается не в том, что две переменные объявлены в той же области, а в том, что C # не позволяет вам иметь одну и ту же переменную в вложенных областях, потому что это может сбивать с толку. C ++ позволяет вам сделать запутанную вещь. - person John Kugelman; 06.08.2010
comment
Джон, конечно, но что именно вы сказали, что сделало мой ответ неуместным или бесполезным (при условии, что вы проголосовали против)? Как я уже сказал, это некоторая справочная информация, и, как сказал ОП: «Спасибо, отличный момент! Это еще лучше проясняет ситуацию ». - person Kieren Johnstone; 06.08.2010
comment
Две str переменные do вызывают ошибку в C #, как и две i переменные. И ни один из них не вызывает ошибку в C ++. Ваш фрагмент кода неверен на любом языке. Я не хочу накапливать, но я думаю, что ваш ответ добавил путанице OP, а не прояснил его. - person John Kugelman; 07.08.2010
comment
@ Джон Кугельман: это моя вина, что я изначально сказал string str = ""; // no scope error. Однако Кирен действительно понял, почему я сначала получаю свою ошибку (потому что последовательность обратима для компилятора). Однако я даю чек Джеффу Деге, потому что он дал более четкий ответ. - person JohnB; 07.08.2010
comment
@John Kugelman - Нет, я не говорил, что это действительный код. Прочтите вопрос еще раз. Я сказал: «Таким образом, ваше сообщение читается так же, как это». И в исходной публикации есть ошибка, поэтому я повторял тот же код, но с перемещенными строками. Я не предлагал решения. Пожалуйста, перечитайте ответы, прежде чем вы решите проголосовать против них; Вы неправы. - person Kieren Johnstone; 07.08.2010