Запрос о области действия локальных переменных в C - PullRequest
2 голосов
/ 14 июня 2010

All

Рассмотрим следующий код:

void func(void)
{
    int a;
    printf ("%d", a);
}

int main(int argc, char **argv)
{
    int a = 3;
    func();
    printf("%d", a);
}

Насколько я понимаю, вывод должен быть:

<junk value><3>

Может ли кто-нибудь подтвердить мое понимание? Мой основной запрос: компилятор обращается к внешней области видимости для переменной, которая была объявлена, но не определена?

С уважением, Негр

Ответы [ 5 ]

10 голосов
/ 14 июня 2010

Ваше понимание верно. func a инициализируется с мусорным стеком.

Каждый раз, когда вы говорите int a;, он создает новую переменную, не имеющую отношения к переменным с одинаковыми именами из окружающих областей или переменных из других функций выше стека вызовов.

В своем оправдании вы вводите в заблуждение Область действия и степень . c использует лексическую область видимости , поэтому, хотя «экстент» (или время жизни) main существует посредством выполнения func, это совершенно другая область действия, поэтому он ссылается на совершенно другую переменную.

Обратите внимание, что "внешняя область видимости" - это, как правило, скобки, находящиеся вне вашей области, а самой внешней областью видимости является уровень файла.

int a; // global
void func(int a) {  // parameter
  int a;  // function local
  while (0) {
    int a;  // scoped in the 'while'
    if (true) { 
      int a;  // scoped in the 'if'
    }
  }
}

Каждая из этих переменных 'a' тени другая 'a над ней.

Исключением (может быть источником вашей путаницы) является переменная, объявленная extern int a;. Эта переменная, в частности, относится к переменной откуда-то еще (другая единица перевода). Внешнее объявление может использоваться для получения поведения, которого вы не ожидали:

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

Исключением из правила "стека мусора" является то, что static и переменные, выделенные из кучи, инициализируются нулями (если я не ошибаюсь, это обеспечивается стандартом).

А также обратите внимание, что «значение мусора» может быть 3.

1 голос
/ 14 июня 2010

Ваш предсказанный результат верен, но ваши рассуждения не совсем. Он никогда не будет ссылаться на переменную a в функции main, поскольку main равно , а не во внешней области видимости func. Даже если он существует во внешней области видимости, он будет скрыт переменной во внутренней области видимости. Пример:

int a = 3;
printf("%d", a);
{
    int a;
    printf ("%d", a);
}

будет печатать <3> <junk value

0 голосов
/ 14 июня 2010

На моем устройстве Solaris 9 с gcc 3.4.2:

#include <stdio.h>

void func(void) 
{ 
    int a; 
    printf ("func:%d ", a); 
    a=9;
} 

int main(int argc, char **argv) 
{ 
    int a = 3; 
    while(a--)
        func(); 
    printf("main:%d\n", a); 
} 

вывод:

> ./a.out
func:-12719276 func:9 func:9 main:-1

'9' происходит из предыдущего воплощения функции.Это означает, что в этой системе функция отображалась в один и тот же кадр стека при каждом ее вызове, поэтому она четко показывает эффект «остатка» мусора.Мы создали это сами.

0 голосов
/ 14 июня 2010

В вашем случае у вас нет ни внешней области видимости, ни внутренней области видимости: у вас есть две локальные области видимости, которые только что заканчиваются внутри блоков, ограниченных { и }.

Так что да, в вашем случаетолько a, определенный внутри func(), будет использоваться printf внутри этой функции.

Аналогичная ситуация, когда у вас фактически есть глобальная переменная области видимости, такая как

int a = 0;

int main(void)
{
  int a;
  printf("%d", a);
}

, приведет к тому же результату junk , так как новое объявление затеняет глобальное.

Компилятору все равно, инициализирована ли переменная или нет, просто позаботьтесь об использовании ближайшего объявления (ближайшего в смысле области видимости).

0 голосов
/ 14 июня 2010

Обе a переменные имеют разные области действия. Представляемый вами правильный вывод.

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