У циклов есть своя собственная запись стека?(иначе, почему этот кодекс законен) - PullRequest
1 голос
/ 20 сентября 2019

Хорошо, поэтому у меня есть небольшой вопрос к вам здесь.

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

Итак, почему этот код допустим:

int x = 1;
while(true) {
    int x = x + 2;
}

Хотя это вызывает ошибку : переопределение 'x'

int x = 1;
int x = 3;

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

Но есть ли у циклов и свои собственные записи стека?На уровне памяти код # 1 не приводит к тому, что у меня N различных ассоциаций для переменной x в одном и том же блоке записи стека?

Короче, почему в коде # 2 я переопределяю переменную x, но в коде № 1 я не?

1 Ответ

2 голосов
/ 20 сентября 2019

Две переменные объявлены в разных областях.

int x = 1;
while(true) {
    int x = x + 2;
}

Переменная, объявленная во внутренней области видимости, скрывает переменную, объявленную во внешней области видимости.

Обратите внимание на то, что это объявление

int x = x + 2;

имеет неопределенное поведение, посколькуобъявленная переменная используется сама в качестве инициализатора, хотя она не была инициализирована.

Например, вы можете написать

int x = 1;

int main( void )
{
   int x = 2;

   while ( 1 )
   {
      int x = 3;
      /*...*/
   }
}

В этой программе объявлены и определены три различных объекта с именем x.

Первая переменная имеет область видимости файла, а две другие имеют области видимости блока.

Что касается фрагмента кода

int x = 1;
int x = 3;

две переменные в одной области видимостиопределены с тем же именем.

В C (но не в C ++) вы можете написать

#include <stdio.h>

int x;
int x = 1;

int main(void) 
{
    return 0;
}

, потому что в области видимости файла это

int x;

неопределение переменной x, но является только ее объявлением.

Также вы можете написать, например,

#include <stdio.h>

int x;
int x = 1;

int main(void) 
{
    extern int x;

    printf( "x = %d\n", x );

    return 0;
}

В строке

    extern int x;

вводится объявление глобальнойпеременная x в блокеscope of main.

Что касается оператора while, то (The C STandard, 6.8.5 Итерационные операторы)

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

...