Страницы

Поиск по вопросам

пятница, 7 декабря 2018 г.

Случаи указания типа данных в условии цикла

Добрый вечер. Пришел с вопросом. Читал тут книгу, в одном фрагменте было написано, что если я укажу тип данных у переменной в условии функции, то значение переменной будет иметь большую область видимости, чем если бы я указал переменную без типа. То есть без типа переменная будет действовать, пока активен цикл, но с типом данных она будет действовать и на еще одни скобки.
Решил проверить. Написал с int'ом-все сработало. Убрал int-и программа стала использовать значение переменной в цикле во всей программе и по какому-то принципу компилятор его даже изменил, по какому-я не понимаю.
Вопрос: Я некорректно понял инфу из учебника? Да, то как все должно быть на самом деле?
#include using namespace std;
int main() { int done=5; int howmany=3;
for( done=1; done cout<Вывод:
7 7 3


Ответ

Рассмотрим следующую программу
#include
int main() { int done = 5; int howmany = 3;
for ( done = 1; done < howmany; done++ ) { std::cout << done << std::endl; }
std::cout << done << std::endl;
return 0; }
Ее вывод на консоль
1 2 3
В этой программе в блоке кода функции main объявлена переменная done. Сначала эта переменная инициализируется значением 5
int done = 5;
а затем в предложении for ей присваивается значение 1
for ( done = 1; done < howmany; done++ ) ^^^^^^^^
После выхода из цикла эта переменная будет иметь значение 3.
Теперь рассмотрим следующую программу
#include
int main() { int done = 5; int howmany = 3;
for ( int done = 1; done < howmany; done++ ) { std::cout << done << std::endl; }
std::cout << done << std::endl;
return 0; }
Ее вывод на консоль
1 2 5
В этой программе в предложении for объявляется переменная с именем done, совпадающем с именем переменной, объявленной в блоке кода main.
for ( int done = 1; done < howmany; done++ ) ^^^^^^^^^^^^
Эта переменная в предложении for скрывает одноименную переменную с таким же именем, объявленную во внешнем блоке кода. Ее область определения - это тело цикла for. После выхода из цикла данная переменная прекращает свое существование.
Из стандарта C++ (6.5.3 The for statement)
3 If the for-init-statement is a declaration, the scope of the name(s) declared extends to the end of the for statement.
Поэтому последняя строка вывода программы
5
уже выводит на консоль значение переменной done, которая была объявлена до цикла в блоке кода функции main
В общем случае имя, объявленное во внутренней области объявления скрывает такое же имя, объявленное во внешней области объявления
Из стандарта C++ (3.3.10 Name hiding)
1 A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).
Обратите внимание, что есть важное отличие в определении предложения for между C++ и C.
В C++ во второй части предложения for, где записывается условие, также может быть объявление.
Рассмотрите следующую демонстрационную программу
#include
int main() { int done = 5; int howmany = 3;
for ( ; int howmany = done; done-- ) { std::cout << done << std::endl; }
std::cout << '
' << howmany << std::endl;
return 0; }
Ее вывод на консоль
5 4 3 2 1
3

При каждой итерации данного цикла for
for ( ; int howmany = done; done-- ) ^^^^^^^^^^^^^^^^^^
объявляется переменная howmany, которая скрывает переменную с таким же именем, объявленную в функции main. Значение, присвоенное этой переменной, преобразуется к булевскому типу. Если оно равно 0, то условие будет ложным и произойдет выход из цикла.
После цикла выводится уже значение переменной howmany, объявленной в main
Ну, и напоследок пример, когда в предложении for сразу в двух его частях объявляются переменные, которые скрывают одноименные переменные с теми же именами, объявленные в main. После выхода из цикла эти переменные прекращают свое существование, и становятся видимыми переменные, объявленные в main
#include
int main() { int done = 10; int howmany = 20;
for ( int done = 5; int howmany = done; done-- ) { std::cout << done << std::endl; }
std::cout << '
' << done << std::endl; std::cout << howmany << std::endl;
return 0; }
Вывод этой программы на консоль
5 4 3 2 1
10 20

Предложение for в этой программе логически может быть представлено как
{ int done = 5;
Label_repeat: { int howmany = done;
if ( howmany != 0 ) { std::cout << done << std::endl; done--; goto Label_repeat; } else { goto Label_exit; } } } Label_exit: //...

Комментариев нет:

Отправить комментарий