Ошибка повторного выделения переменной цикла внутри цикла - PullRequest
0 голосов
/ 01 мая 2018

Рассмотрим этот фрагмент программы на C:

for(int i = 0; i < 5; i++)
{
    int i = 10;  // <- Note the local variable

    printf("%d", i); 
}    

Компилируется без ошибок и при выполнении выдает следующий вывод:

1010101010

Но если я напишу похожий цикл в C ++:

for(int i = 0; i < 5; i++)
{
     int i = 10;

     std::cout << i; 
}

Компиляция завершается с этой ошибкой:

prog.cc:7:13: error: redeclaration of 'int i'  
     int i = 10;  
         ^  
prog.cc:5:13: note: 'int i' previously declared here  
     for(int i = 0; i < 5; i++)  
             ^   

Почему это происходит?

Ответы [ 3 ]

0 голосов
/ 01 мая 2018

В отличие от C, в C ++ есть правило,
C ++ 11-§6.5.3 / 1:

оператор for

for ( for-init-statement condition<sub>opt</sub> ; expression<sub>opt</sub> ) statement 

эквивалентно

{
    for-init-statement 
    while ( condition ) {
        statement 
        expression ;
    } 
}

за исключением того, что имена, объявленные в for-init-Statement , находятся в той же декларативной области , что и объявленные в условии [...]

Это означает, что область действия for-init-statement и statement совпадают *, а приведенный ниже код вызовет ошибку

for(int i = 0; i < 5; i++){
     int i = 10;    // Invalid. 
     // ...
}

В С,
C11-§6.8.5 / 5:

Оператор итерации - это блок, область действия которого является строгим подмножеством области действия включающего его блока. Тело цикла также является блоком, область действия которого является строгим подмножеством области действия оператора итерации .

Следовательно, statement имеет собственную область видимости, и приведенный выше код действителен и эквивалентен

for(int i = 0; i < 5; i++){
    {
         int i = 10;    // Valid. 
         // ...
    }
}

Рекомендуемое чтение: n3337: 6.5.1 Оператор while / p (2). Та же ссылка может быть найдена в проекте c ++ 17 (n4659) в разделах § 9.5.1 и §9.5.3.

0 голосов
/ 11 июля 2018

Это не повторная реклама.

Смотри внимательно ...

for(int i = 0; i < 7; i++)
{
    printf("i = %d\n", i);
    int i = 5;
    printf("new i = %d\n", i);
}

Вывод вышеуказанного кода: -

i = 0
new i = 5
i = 1
new i = 5
i = 2
new i = 5
i = 3
new i = 5
i = 4
new i = 5
i = 5
new i = 5
i = 6
new i = 5

Очевидно, есть два разных i

Более новый i имеет более локальную область видимости.

Это ошибка?

нет

Нет

Какова цель?

Если это не разрешено, поддерживать большие проекты может быть очень сложно, так как вы постоянно сталкиваетесь с конфликтами имен.

Как правило, считается очень плохой практикой присваивать одно и то же имя разным переменным в разных областях, и вам следует избегать этого по возможности.

Почему нет предупреждающего сообщения?

Используйте gcc file_name.c -Wshadow для компиляции.


РЕДАКТИРОВАТЬ: Вы также можете локально заблокировать первоначально объявленные переменные путем повторного выделения их для циклов.

0 голосов
/ 01 мая 2018

Это связано с тем, что языки C и C ++ имеют разные правила повторного объявления переменных в области видимости, вложенной в цикл for:

  • C++ помещает i в область видимости цикла, поэтому вторая int i = 10 - это переопределение, которое запрещено
  • C позволяет переопределение в области видимости внутри цикла for; внутренняя переменная "выигрывает"

Вот демонстрация работающей программы на C и программы C ++, которая не компилируется .

Открытие вложенной области видимости внутри тела исправляет ошибку компиляции ( demo ):

for (int i =0 ; i != 5 ; i++) {
    {
        int i = 10;
        cout << i << endl;
    }
}

Теперь i в заголовке for и int i = 10 находятся в разных областях, поэтому программа может быть запущена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...