Почему результат отличается, когда мы дважды добавляем тег int в программе при использовании for l oop? - PullRequest
2 голосов
/ 02 августа 2020

Я изучаю и плохо знаком с языком C. Пока я создавал функцию, которая будет давать мощность двух чисел, используя для l oop, я обнаружил, что использование объявления int перед запуском l oop, а также в l oop изменяет вывод моей программы. Почему это так?

Код с использованием объявления int один раз с правильным выводом;

# include<stdio.h>

int main()
{
    int x, y;
    int r = 1;
    int k;
    printf("Enter base number:");
    scanf("%d", &x);
    printf("Enter power");
    scanf("%d", &y);
    for (k = 1; k <= y; k++)
    {
       r = r * x;
    }
    printf("Power is %d", r);
    return 0;
}

Правильный вывод:

Enter base number:7
Enter power3
Power is 343

Неверный код 2:

# include<stdio.h>

int main()
{
    int x, y;
    int r = 1;
    int k;
    printf("Enter base number:");
    scanf("%d", &x);
    printf("Enter power");
    scanf("%d", &y);
    for (k = 1; k <= y; k++)
    {
       int r = r * x;
    }
    printf("Power is %d", r);
    return 0;
}

Неправильный вывод:

Enter base number:7
Enter power3
Power is 1

Подскажите, пожалуйста, почему это так.

Ответы [ 4 ]

4 голосов
/ 02 августа 2020
for (k = 1; k <= y; k++)
{
   int r = r * x;
}

int r внутри for l oop объявляет отдельную и уникальную переменную, которая видна только в области for l oop.

This r не относится к r за пределами for l oop.

Но внутри части инициализации l oop (внутренних) r, внутренний r не затеняет внешний r, потому что объявление внутреннего r не выполняется в этот момент времени.

Итак, r в r * x относится к внешний r, а не внутренний.

Если бы вы написали:

for (k = 1; k <= y; k++)
{
   int r = 2; 
   r = r * x;
}

, тогда все r относились бы к внутреннему r и полностью затеняли бы внешний.

После этого, когда вы используете

printf("Power is %d", r);

, он печатает значение внешней переменной r, которое остается неизменным. Это подтверждается выводом

Power is 1

Боковое примечание:

  • На самом деле не имеет большого смысла объявлять переменные внутри тела l oop, поскольку вы указываете объявлять новую переменную на каждой итерации. Компилятор может оптимизировать это только до одного определения, но лучше размещать объявления внутри части инициализации for l oop или объявлять их перед l oop.
1 голос
/ 02 августа 2020

Во втором фрагменте кода int r = r * x; объявляет новую переменную с именем r, которая существует только на протяжении каждой итерации for l oop. Кроме того, это объявление скрывает (или тени ) предыдущую переменную с тем же именем из области действия этого l oop, поэтому любые изменения, внесенные в r в l oop, не влияют на 'исходная' r переменная.

Включение предупреждений компилятора обычно выявляет такие проблемы. Например, для вашего второго фрагмента кода компилятор clang-cl дает следующее:

предупреждение: объявление затеняет локальную переменную [-Wshadow]

1 голос
/ 02 августа 2020

Поскольку «область действия» r во втором коде находится внутри l oop, при выходе из l oop переменная больше не действительна.

  for (k = 1; k <= y; k++)
  {
       int r = r * x; //here you create the variable
  } //here it is destroyed

В c / c ++ переменные являются локальными для области видимости, когда вы покидаете область видимости, вы теряете переменную. Все внутри {} - это область действия (внутренняя по отношению к внешней области). Внутри области видимости можно видеть переменные вне области видимости.

void func()
{ // begin scope of a function

   // can't see any variables defined inside the scope of the while
   // they don't exists yet
   while ()
   { // begin scope of a while
     // can see variables defined inside the scope of the function
   }

   // can't see any variables defined inside the scope of the while
   // they don't exists anymore
}
1 голос
/ 02 августа 2020

Для первого фрагмента кода r = r * x относится к r, определенному вне для l oop, что означает, что он работает должным образом. Для второго фрагмента кода, когда вы выполняете int r = r * x, вы объявляете другой r с областью действия для l oop, и изменения не отражаются во external r. Затем, вне для l oop, вы переключаетесь обратно на внешний r, который по-прежнему равен 1.

...