Що буде надруковано? 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;
}
Відповіді:
Тут є два питання, час життя та сфера застосування.
Область змінної - це те, де можна побачити ім'я змінної. Тут х видно лише всередині функції foo ().
Час життя змінної - це період, протягом якого вона існує. Якби x було визначено без ключового слова static, час життя був би від вступу в foo () до повернення з foo (); тож вона буде повторно ініціалізована до 5 при кожному дзвінку.
Статичне ключове слово діє для продовження терміну служби змінної до терміну служби програми; наприклад, ініціалізація відбувається лише раз і один раз, і тоді змінна зберігає своє значення - яким би воно не було - для всіх майбутніх викликів 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;
}
Все, що робить статичне ключове слово в цій програмі, це те, що він повідомляє компілятору (по суті) "ей, у мене є змінна тут, що я не хочу, щоб хто-небудь інший отримував доступ, і не говорив нікому ще, що вона існує".
Всередині методу статичне ключове слово повідомляє компілятору те саме, що вище, але також "не кажіть нікому, що це існує поза цією функцією, воно повинне бути доступним лише у цій функції".
Я сподіваюся, що це допомагає
x
головним; це глобально. У первісному прикладі 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
. Статична змінна (всередині функції чи ні) ініціалізується рівно один раз перед виконанням будь-якої функції в цьому блоці перекладу. Після цього він зберігає своє значення до зміни.
Вадиклк,
Чому ...? Причина полягає в тому, що статична змінна ініціалізується лише один раз і зберігає своє значення у всій програмі. значить, ви можете використовувати статичну змінну між викликами функцій. також його можна використовувати для підрахунку "скільки разів викликається функція"
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 Оскільки статична змінна використовується лише один раз, то 5 ++ стає 6 при 1-му дзвінку 6 ++ стає 7 при другому виклику Примітка. Коли відбувається другий виклик, він приймає значення 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", тоді це не потрібно, і змінна може бути ініціалізована при завантаженні програми за допомогою значення, збереженого компілятором у вихідному коді складання.