Что будет напечатано? 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;
}
То же самое, что и следующая программа:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Все, что статическое ключевое слово делает в этой программе, это указание компилятору (по существу): "Привет, у меня есть переменная здесь, что я не хочу, чтобы кто-либо еще обращался к ней, не говорите никому другому, что она существует".
Внутри метода ключевое слово static сообщает компилятору то же, что и выше, но также: "Не говорите никому, что это существует вне этой функции, оно должно быть доступно только внутри этой функции".
Я надеюсь, что это поможет
6 7
компилятор устанавливает, что статическая инициализация переменных не происходит при каждом вводе функции
Статическая переменная внутри функции имеет продолжительность жизни, пока ваша программа работает. Он не будет выделяться каждый раз, когда ваша функция вызывается и освобождается при возврате функции.
Выход будет 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.
В свою очередь, автоматические (локальные) переменные хранятся в Stack, и все переменные в стеке повторно инициализируются все время, когда функция вызывается, поскольку для нее создается новая FAR (запись активации функции).
в порядке для понимания, выполните приведенный выше пример без "статического" и сообщите, какой будет выход. Это поможет вам понять разницу между этими двумя.
Спасибо Джавед
Давайте просто прочитаем статью Википедии о статических переменных...
Статические локальные переменные: переменные, объявленные как статические внутри функции, статически распределяются, имея ту же область, что и автоматические локальные переменные. Следовательно, любые значения, которые функция помещает в свои статические локальные переменные во время одного вызова, все еще будут присутствовать, когда функция будет вызвана снова.
Вы получите 6 7 напечатанных как, как легко проверить, и здесь причина: Когда сначала вызывается foo
, статическая переменная x инициализируется до 5. Затем она увеличивается до 6 и печатается.
Теперь для следующего вызова foo
. Программа пропускает инициализацию статической переменной и вместо этого использует значение 6, которое было присвоено x в последний раз. Выполнение выполняется как обычно, давая вам значение 7.
6 7
x - глобальная переменная, которая видна только из foo(). 5 - его начальное значение, которое хранится в разделе .data кода. Любая последующая модификация перезаписывает предыдущее значение. В корпусе функции отсутствует код назначения.
6 и 7 Поскольку статическая переменная intialise только один раз, Таким образом, 5 ++ становится 6 при первом вызове 6 ++ становится 7 при 2-м вызове Примечание. Когда происходит 2-й вызов, значение x равно 6 вместо 5, потому что x является статической переменной.
Объявление x
находится внутри foo
но инициализация x=5
происходит вне foo
!
Нам нужно понять, что
static int x = 5;
это не то же самое, что
static int x;
x = 5;
В других ответах использовались важные слова здесь, область действия и время жизни, и указывалось, что область действия x
находится от точки ее объявления в функции foo
до конца функции foo
. Например, я проверил, перемещая объявление в конец функции, и это делает x
необъявленным в x++;
выражение.
Таким образом, static int x
(сфера) часть заявления фактически применяется, когда вы читаете это, где - то внутри функции, и только оттуда вперед, а не над ним внутри функции.
Однако x = 5
(время жизни) часть инструкции является инициализацией переменной и происходит OUTSIDE функции как часть загрузки программы. При загрузке программы изменяется переменная x
со значением 5
.
Я прочитал это в одном из комментариев: "Кроме того, это не относится к действительно запутанной части, которая заключается в том, что инициализатор пропускается при последующих вызовах". Он пропускается при всех вызовах. Инициализация переменной вне собственного кода функции.
Значение 5 теоретически устанавливается независимо от того, вызывается ли вообще foo, хотя компилятор может оптимизировать функцию, если вы ее не назовете. Значение 5 должно быть в переменной до того, как будет вызван foo.
Внутри foo
утверждение static int x = 5;
вряд ли будет генерировать какой-либо код вообще.
Я нашел, что адрес x
использует, когда я помещаю функцию foo
в мою программу, а затем (правильно) догадался, что это же место будет использоваться, если я снова запустил программу. Частичный снимок экрана ниже показывает, что x
имеет значение 5
еще до первого вызова foo
.
По крайней мере, в С++ 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, это не требуется, и переменная может быть инициализирована при загрузке программы, используя значение, сохраненное компилятором в выходном коде сборки.