Что будет распечатано? 6 6 или 6 7? И почему?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Что будет распечатано? 6 6 или 6 7? И почему?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Ответы:
Здесь есть две проблемы: срок службы и область действия.
В области видимости переменной можно увидеть имя переменной. Здесь x виден только внутри функции foo ().
Время жизни переменной - это период, в течение которого она существует. Если бы x был определен без ключевого слова static, время жизни было бы от входа в foo () до возврата из foo (); поэтому он будет повторно инициализирован до 5 при каждом вызове.
Ключевое слово static продлевает время жизни переменной до времени жизни программы; например, инициализация происходит один раз и только один раз, а затем переменная сохраняет свое значение - каким бы оно ни было - во всех будущих вызовах foo ().
Выход : 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;
}
6 7
компилятор обеспечивает то, что инициализация статической переменной не происходит каждый раз при входе в функцию
Это то же самое, что и следующая программа:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Все, что ключевое слово static делает в этой программе, - это сообщает компилятору (по сути): «Эй, у меня есть переменная, к которой я не хочу, чтобы кто-либо другой получал доступ, не говорите никому, что она существует».
Внутри метода ключевое слово static сообщает компилятору то же самое, что и выше, но также «никому не говорите, что это существует вне этой функции, оно должно быть доступно только внутри этой функции».
надеюсь, это поможет
x
в main; это глобально. В исходном примере x
был локальным для foo, видимым только внутри этого блока, что обычно предпочтительнее: если foo существует для поддержки x
предсказуемым и видимым образом, то позволять другим тыкать его, как правило, опасно. Еще одно преимущество - держать его в объеме. foo()
Он также сохраняет foo()
портативность.
c
, поэтому в этом контексте ваш пример будет незаконным в глобальной области. (C требует постоянных инициализаторов для глобальных объектов, C ++ - нет).
Статическая переменная внутри функции имеет срок жизни, пока выполняется ваша программа. Он не будет выделяться каждый раз, когда ваша функция вызывается, и освобождается, когда ваша функция возвращается.
Объявление x
находится внутри, foo
но x=5
инициализация происходит вне foo
!
Здесь нам нужно понять, что
static int x = 5;
это не то же самое, что
static int x;
x = 5;
В других ответах здесь использовались важные слова, область видимости и время жизни, и было указано, что область действия x
находится от точки ее объявления в функции foo
до конца функции foo
. Например, я проверил, переместив объявление в конец функции, и это x
стало необъявленным в x++;
заявлении.
Таким образом, часть static int x
(область действия) оператора действительно применяется там, где вы ее читаете, где-то ВНУТРИ функции и только оттуда и далее, а не над ней внутри функции.
Однако часть x = 5
(время жизни) оператора - это инициализация переменной и выполнение ВНЕШНЕЙ функции во время загрузки программы. Переменная x
рождается со значением5
когда программа загружается.
Я прочитал это в одном из комментариев: « Кроме того, это не решает действительно сбивающую с толку часть, а именно то, что инициализатор пропускается при последующих вызовах. Он пропускается при всех вызовах. Инициализация переменной происходит вне кода функции.
Значение 5 теоретически устанавливается независимо от того, вызывается ли вообще foo, хотя компилятор может оптимизировать функцию, если вы ее нигде не вызываете. Значение 5 должно быть в переменной до вызова foo.
Внутри foo
заявленияstatic int x = 5;
вряд ли вообще будет генерироваться какой-либо код.
Я обнаружил, что адрес x
используется, когда я помещаю функцию foo
в свою программу, а затем (правильно) предположил, что это же местоположение будет использовано, если я снова запущу программу. На частичном снимке экрана ниже показано, что x
значение имеет значение 5
еще до первого вызова foo
.
На выходе будет 6 7
. Статическая переменная (внутри функции или нет) инициализируется ровно один раз перед выполнением какой-либо функции в этой единице перевода. После этого он сохраняет свое значение до тех пор, пока не будет изменен.
Vadiklk,
Зачем ...? Причина в том, что статическая переменная инициализируется только один раз и сохраняет свое значение на протяжении всей программы. означает, что вы можете использовать статическую переменную между вызовами функций. также его можно использовать для подсчета «сколько раз вызывается функция»
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.
В свою очередь, автоматические (локальные) переменные сохраняются в стеке, и все переменные в стеке повторно инициализируются все время, когда функция вызывается, поскольку для этого создается новый FAR (запись активации функции).
хорошо, для большего понимания, сделайте приведенный выше пример без «статики» и сообщите, каким будет результат. Это заставит вас понять разницу между этими двумя.
Спасибо Джавед
Давайте просто прочитаем статью в Википедии о статических переменных ...
Статические локальные переменные: переменные, объявленные как статические внутри функции, статически выделяются, имея ту же область действия, что и автоматические локальные переменные. Следовательно, любые значения, которые функция помещает в свои статические локальные переменные во время одного вызова, все равно будут присутствовать при повторном вызове функции.
Вы получите 6 7, напечатанное как, что легко проверить, и вот почему: когда foo
первом вызове статическая переменная x инициализируется значением 5. Затем она увеличивается до 6 и печатается.
Теперь о следующем звонке foo
. Программа пропускает инициализацию статической переменной и вместо этого использует значение 6, которое было присвоено x в последний раз. Выполнение продолжается как обычно, и вы получаете значение 7.
6 и 7 Поскольку статическая переменная инициализируется только один раз, Итак, 5 ++ становится 6 при 1-м вызове, 6 ++ становится 7 при 2-м вызове. Примечание. Когда происходит 2-й вызов, он принимает значение x, равное 6, а не 5, потому что x является статической переменной.
По крайней мере, в C ++ 11, когда выражение, используемое для инициализации локальной статической переменной, не является constexpr (не может быть оценено компилятором), инициализация должна происходить во время первого вызова функции. Самый простой пример - напрямую использовать параметр для инициализации локальной статической переменной. Таким образом, компилятор должен выдать код, чтобы угадать, является ли вызов первым или нет, что, в свою очередь, требует локальной логической переменной. Я собрал такой пример и убедился, что это правда, посмотрев код сборки. Пример может быть таким:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
конечно, когда выражением является constexpr, это не требуется, и переменная может быть инициализирована при загрузке программы с использованием значения, сохраненного компилятором в выходном ассемблерном коде.