Статическая переменная внутри функции в C - PullRequest
98 голосов
/ 17 февраля 2011

Что будет распечатано? 6 6 или 6 7? А почему?

void foo()
{
    static int x = 5;
    x++;
    printf("%d", x);
}

int main()
{
    foo();
    foo();
    return 0;
}

Ответы [ 13 ]

153 голосов
/ 17 февраля 2011

Здесь есть две проблемы: время жизни и область действия.

Область действия переменной - это место, где можно увидеть имя переменной.Здесь x виден только внутри функции foo ().

Время жизни переменной - это период, в течение которого она существует.Если бы x было определено без ключевого слова static, время жизни было бы от входа в foo () до возврата из foo ();поэтому при каждом вызове он будет повторно инициализирован до 5.

Ключевое слово static действует, чтобы продлить время жизни переменной до времени жизни программы;например, инициализация происходит один раз и только тогда, и тогда переменная сохраняет свое значение - каким бы оно ни было - во всех будущих вызовах foo ().

42 голосов
/ 21 мая 2014

Выход : 6 7

Причина : статическая переменная инициализируется только один раз (в отличие от автоматической переменной), и дальнейшее определение статической переменной будет пропущено во время выполнения. И если он не инициализируется вручную, он инициализируется значением 0 автоматически. Итак,

void foo() {
    static int x = 5; // assigns value of 5 only once
    x++;
    printf("%d", x);
}

int main() {
    foo(); // x = 6
    foo(); // x = 7
    return 0;
}
9 голосов
/ 17 февраля 2011

Это то же самое, что иметь следующую программу:

static int x = 5;

void foo()
{
    x++;
    printf("%d", x);
}

int main()
{
     foo();
     foo();
     return 0;
}

Все, что статическое ключевое слово делает в этой программе, это говорит компилятору (по сути): «Эй, у меня есть переменная, которую я наделилне хочу, чтобы кто-то еще обращался к нему, не говорите никому, что он существует ».

Внутри метода ключевое слово static сообщает компилятору то же, что и выше, но также« не говорите никому, что это существует ».вне этой функции он должен быть доступен только внутри этой функции.

Надеюсь, это поможет

9 голосов
/ 17 февраля 2011

6 7

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

5 голосов
/ 17 февраля 2011

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

3 голосов
/ 05 марта 2018

Выход: 6,7

Причина

Объявление x находится внутри foo, но инициализация x=5 происходит вне foo!

Нам нужно понять, что

static int x = 5;

не совпадает с

static int x;
x = 5;

В других ответах использовались важные слова здесь, область действия и время жизни, и указывалось, что область действия x находится от точки ее объявления в функции foo до конца функции foo. Например, я проверил, переместив объявление в конец функции, и это делает x необъявленным в операторе x++;.

Таким образом, часть static int x (scope) оператора действительно применяется там, где вы ее читаете, где-то INSIDE функции и только оттуда, а не над ней внутри функции.

Однако часть оператора x = 5 (время жизни) - это инициализация переменной и выполнение OUTSIDE функции при загрузке программы. Переменная x создается со значением 5 при загрузке программы.

Я прочитал это в одном из комментариев: « Кроме того, это не касается действительно запутанной части, которая заключается в том, что инициализатор пропускается при последующих вызовах. » Он пропускается на всех звонки. Инициализация переменной находится за пределами собственно кода функции.

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

Внутри foo оператор static int x = 5; вряд ли вообще сгенерирует код.

Я обнаружил, что адрес x используется, когда я поместил функцию foo в мою программу, а затем (правильно) предположил, что то же место будет использоваться, если я снова запустил программу. Приведенный ниже частичный снимок экрана показывает, что x имеет значение 5 даже до первого вызова foo.

Break Point before first call to foo

2 голосов
/ 05 декабря 2013

Вадиклк,

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

main()
{
   static int var = 5;
   printf("%d ",var--);
   if(var)
      main();
} 

и ответ 5 4 3 2 1, а не 5 5 5 5 5 5 .... (бесконечный цикл) каквы ожидаете.опять же, причина в том, что статическая переменная инициализируется один раз, когда при следующем вызове main () она не будет инициализирована значением 5, поскольку она уже инициализирована в программе. Поэтому мы можем изменить значение, но не можем повторно инициализировать.Вот как работает статическая переменная.

или вы можете рассмотреть как для хранилища: статические переменные хранятся в разделе данных программы, а переменные, которые хранятся в разделе данных, инициализируются один раз.и до инициализации они хранятся в секции BSS.

В свою очередь, переменные Auto (local) сохраняются в стеке, и все переменные в стеке повторно инициализируются все время, когда функция вызывается как новая FAR (запись активации функции)для этого.

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

Спасибо, Джавед

2 голосов
/ 17 февраля 2011

Выход будет 6 7. Статическая переменная (независимо от того, находится она внутри функции или нет) инициализируется ровно один раз перед выполнением любой функции в этом модуле перевода. После этого он сохраняет свое значение до изменения.

1 голос
/ 07 июня 2014

6 и 7 Поскольку статическая переменная инициализируется только один раз, то 5 ++ становится 6 при первом вызове 6 ++ становится 7 при втором вызове Примечание. Когда происходит второй вызов, он принимает значение x вместо 6, потому что x является статической переменной.

1 голос
/ 17 февраля 2011
6 7

x - глобальная переменная, видимая только из foo ().5 является его начальным значением, которое хранится в разделе кода .data.Любая последующая модификация перезаписывает предыдущее значение.В теле функции не генерируется код назначения.

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