Внутрішньо всі змінні, локальні для функції, розподіляються в стеку або всередині регістрів ЦП, а потім згенерований машинний код міняється місцями між регістрами та стеком (так званий регістр розливу), якщо компілятор поганий або якщо ЦП не має достатньо регістрів для тримайте всі кульки жонглюючи у повітрі.
Для розподілу речей у стеку, ЦП має два спеціальні регістри, один називається покажчиком стека (SP), а інший - базовим покажчиком (BP) або покажчиком кадру (мається на увазі, що кадр стека локальний до поточної області функцій). SP вказує на поточне розташування у стеці, тоді як BP вказує на робочий набір даних (над ним) та аргументи функції (під ним). Коли функція викликається, вона штовхає BP виклику / батьківської функції у стек (вказаний SP) і встановлює поточний SP як новий BP, потім збільшує SP на кількість байтів, пролитих з регістрів на стек, робить обчислення , а після повернення він відновлює АТ свого батька, витягуючи його зі стека.
Як правило, збереження змінних всередині їх власного {}
-cope може прискорити компіляцію та покращити згенерований код за рахунок зменшення розміру графіка, який компілятор повинен пройти, щоб визначити, які змінні де і як використовуються. У деяких випадках (особливо коли задіяний goto) компілятор може пропустити той факт, що змінна більше не використовуватиметься, якщо ви явно не повідомляєте компілятору обсяг її використання. Компілятори можуть мати обмеження часу / глибини для пошуку графіку програми.
Компілятор може розмістити змінні, оголошені поруч один з одним, в одну і ту ж область стека, що означає, що завантаження однієї попередньо завантажить усі інші в кеш. Таким же чином, оголошення змінної register
, може дати компілятору натяк про те, що ви хочете уникнути розлиття зазначеної змінної у стеку за будь-яку ціну.
Суворий стандарт C99 вимагає явного {
перед оголошеннями, тоді як розширення, введені C ++ та GCC, дозволяють декларувати vars далі в тілі, що ускладнює goto
та case
твердження. C ++ додатково дозволяє оголошувати речі всередині для ініціалізації циклу, що обмежується сферою дії циклу.
І останнє, але не менш важливе: для іншої людини, яка читає ваш код, було б приголомшливо, коли він побачить верх функції, заповнену дев’ятьма оголошеннями змінних, замість того, щоб вони були локалізовані в місцях їх використання. Це також полегшує коментування їх використання.
TLDR: використання, {}
щоб явно вказати область змінних, може допомогти як компілятору, так і користувачеві.
gcc
досить розслаблений. Ви використовуєте масиви та декларації змінної довжини c99. Скомпілюйте,gcc -std=c89 -pedantic
і на вас закричать. Відповідно до c99, все, що це кошерно.