Структура кадра стека для функции с подпространством

Ниже приведен код, который я взял в качестве ссылки, чтобы понять, как вспомогательная область (или) фиктивная область видимости (просто {}), присутствующая в функции, влияет на структуру кадра стека.

#include <stdio.h>
int main()
{
   int main_scope=0; /*Scope and life time of the variable is throughout main*/

   {
     //From below two statements I assume that there
     //is no seperate "stack frame" created for just
     //braces {}.So we are free access (scope exists) and
     //modify (lifetime exists) the variable "main_scope"
     //anywhere within main

     main_scope++;
     printf("main_scope++:(%d)\n",main_scope);

    //I expected this statement to throw an error saying
    //"Multiple definition for "main_scope".But it isn't????

    int main_scope=2;
    printf("Value of redefined main_scope:(%d)\n",main_scope);

  }

  printf("Finally main_scope in %s:(%d)\n",__FUNCTION__,main_scope);
  return 0;
}

Пример вывода

main_scope++:(1)
Value of redefined main_scope:(2)
Finally main_scope in main:(1)

Основываясь на приведенном выше поведении, я предполагаю следующее.

  • Для области {} не создается фрейм стека.
  • Таким образом, переменные auto, объявленные / определенные в main и находящиеся в подпространстве {}, используют один и тот же фрейм стека.
  • Таким образом, переменные, объявленные / определенные в main, могут быть доступны в любом месте функции (даже в подпространстве).
  • С другой стороны, переменные, объявленные / определенные в подпространстве теряют свою область видимости вне блока, но время их жизни действительно до тех пор, пока присутствует кадр стека.

Вопрос: Если приведенные выше пункты верны, то почему код не дает сбоев при предоставлении нескольких определений одной и той же переменной, одно в пределах main, а другое - в {}.


person Vivek Maran    schedule 13.10.2012    source источник
comment
Вы проверили параметры компилятора? Возможно, это поведение можно настроить.   -  person Chris O    schedule 13.10.2012


Ответы (2)


Аппаратный стек здесь не имеет значения. Он может увеличиваться только один раз для всех локальных переменных при входе в функцию и сокращаться только один раз при выходе из функции или может увеличиваться и уменьшаться каждый раз, когда определяется новая локальная переменная, и уничтожается, когда для нее остается закрывающий {}.

Что важно, так это «видимость» переменных.

int main_scope=0;

{
    main_scope++;
    printf("main_scope++:(%d)\n",main_scope);
    // the main_scope variable that was assigned 0 is the most recent
    // visible declaration of main_scope.

    int main_scope=2;
    // now, the previous declaration of main_scope is obscured by the new one,
    // and so, you're going to access the new one
    printf("Value of redefined main_scope:(%d)\n",main_scope);
}

printf("Finally main_scope in %s:(%d)\n",__FUNCTION__,main_scope);
// the previous scope inside {} is left, so, main_scope is going to be
// the one, to which we assigned 0

Совершенно законно определять объект во внутренней / подобласти с тем же именем, что и во внешней / надобласти. Последний будет скрыт на время действия области {}.

Для справки есть еще несколько мест, где могут встречаться определения переменных, например внутри первого выражения оператора for(;;): for (int i = 0; i < 10; i++) .... Эта переменная i будет видна только внутри тела for, и вы также можете скрыть ее там, определив другой i.

person Alexey Frunze    schedule 13.10.2012
comment
Алексей Спасибо за ответ, int main_scope=0; int main_scope=1; выдает ошибку, значит, int main_scope=0; {int main_scope=1;} тоже должно выдавать ошибку, не так ли? Хотя определение внутри {} пытается инициализировать новую переменную, оно должно конфликтовать с существующей переменной main_scope, присутствующей в кадре стека, - это то, что я ожидал. Пожалуйста, укажите мне, если где-то я ошибаюсь. - person Vivek Maran; 13.10.2012
comment
Вы не можете определить 2 объекта с одинаковыми именами в одной и той же области, поэтому первый вызывает ошибку компиляции, но вы можете определять объекты с одинаковыми именами в разных областях, и это нормально, поэтому второй компилируется. - person Alexey Frunze; 13.10.2012

Локальная переменная скрывает внешнюю переменную main_scope.

int main()
{
    int i=1;
    {

      int i=2;
      printf("%d", i);
      /* Whenever you use i here, it's always the local one that's used. 
      The outer i is hidden by the local i. But the local i will be deallocated 
      once the scope exits.*/
    } 
}

совершенно законно в C. (обратите внимание, что это незаконно в C ++!)

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

person P.P    schedule 13.10.2012