Змінні С++

Атрибути змінних[1] ред.

Змінна — це абстрактна назва комірки чи декількох послідовних комірок пам'яті. Комірка це окрема одиницю пам'яті, що має адресу. Як правило, у більшості сучасних комп'ютерів розмір комірки дорівнює одному байту, що складається з восьми бітів.

Кожна змінна має шість атрибутів: ім'я, адресу, значення, тип, область видимості і час життя.

Адреса змінної — це адреса комірок пам'яті, зв'язаних з даною змінною. Якщо змінна займає декілька комірок, її адресою вважається адреса першої комірки. У різних місцях програми можуть існувати різні змінні, що мають однакові імена, але різні адреси. Наприклад, якщо програма складається з двох функцій f1() і f2(), у кожній з них можна визначити змінну, що має те саме ім'я, скажемо var. Це різні змінні, оскільки вони зв'язані з різними функціями і відділені одна від одної невидимою стіною, що обмежує їхню область видимості. Такі змінні називаються локальними. Вони з'являються усередині функцій чи окремих блоків. Глобальні змінні доступні в будь-якій точці програми. Оголошення глобальної змінної повинне знаходитися поза будь-якою функцією. Їхні імена також можуть збігатися з іменами локальних змінних (таке явище називається маскуванням), але при цьому виникає конфлікт імен. Для його розв’язання існує особливий засіб — оператор розв’язування області видимості ::. Глобальна змінна існує від моменту її оголошення і знищується після завершення роботи програми.

Значення змінної — це двійкове число, записане в комірках пам'яті, зв'язаних з даною змінною.

Тип змінної визначає діапазон значень, що вона може набувати, і набір операцій, що до неї можна застосовувати. Поняття типу в мові С++ є принципово важливим, тому ми розглянемо його окремо, а поки зупинимося на концепції зв'язування, що також представляє дуже великий інтерес.

Зв'язування — це процес установлення зв'язку між атрибутом і змінною. Момент, коли цей зв'язок установлюється, називається часом зв'язування. Зв'язування може відбуватися під час компіляції або виконання програми, у залежності від цього розрізняють статичне і динамічне зв'язування. Змінна стає доступною, лише якщо вона зв'язана з типом даних. Тут важливі два моменти: яким чином указується тип і коли відбувається зв’язування. У мовах програмування тип указується за допомогою оголошення: явного чи неявного. Явне оголошення — це оператор програми, у якому перераховані імена змінних і зазначений їхній тип. Неявне оголошення — це механізм зв'язування змінних з типами на основі прийнятих угод. У цьому випадку оператор оголошення не потрібний — перша поява імені змінної в програмі вважається її неявним оголошенням. Класичний приклад неявного оголошення змінних можна зустріти в програмах мовою FORTRAN, у якому всі змінні, імена яких починаються з букв I, J, K, L, M і N, за замовчуванням вважаються цілочисельними, а інші — дійсними. І явне, і неявне оголошення є статичними.

Область видимості і час життя змінної тісно зв'язані між собою. Будь-яку змінну необхідно зв'язати з однією або декількома комірками пам'яті. Для цього адресу комірки необхідно отримати зі списку вільної пам'яті (купи). Цей процес називається розміщенням змінної в пам'яті. Зворотний процес називається видаленням змінної з пам'яті, чи знищенням об'єкта. Він полягає в тім, що адреса комірок, раніше виділених для збереження змінної, повертається в список вільної пам'яті.

Час життя змінної — це відрізок часу, протягом якого змінна зв'язана з визначеною коміркою пам'яті. Отже, початком існування змінної варто вважати момент її зв'язування з визначеними комірками пам'яті, а кінцем — момент її відкріплення від цих комірок.

Основні типи даних[2] ред.

Символи ред.

Символьні дані подаються у вигляді цифрових кодів відповідно до системи кодування ASCII (American Standard Code for Information Interchange — Американський стандартний код обміну інформацією), у якій для кодування 128 різних символів використовується діапазон значень 0–127. Для обробки цих кодів у мові С++ передбачений окремий елементарний тип — char. В даний час програми уже не обмежуються англійською мовою. Програми, що розповсюджуються Інтернетом, повинні підтримувати різні національні алфавіти, що, як відомо, відрізняються великим розмаїттям. Це змусило розроблювачів стандарту мови С++ включити в нього тип розширеного символу wchar_t. Розмір цього типу залежить від ілятора (у Visual C++ він дорівнює 2 байт, а в старих іляторах — 1 байт). Строго говорячи, тип whar_t не є самостійним. У залежності від ілятора він перевизначається на основі одного з елементарних типів.

Логічні змінні ред.

Логічні змінні належать до булевого типу, що позначається ключовим словом bool. Вони набувають лише два значення — істина і хибність. Донедавна як логічні значення використовувалися лише цілі числа. У виразах, що використовують такі операнди, будь-які ненульові значення є істинними, а нуль вважається помилковим значенням. У ході стандартизації мови С++ цей недолік був виправлений, і з'явився особливий тип bool. Змінні цього типу набувають два значення: true і false. Таким чином, програмісти можуть самі вибирати, яким способом користатися. Перевагу має, звичайно, новий стиль. Він більш простий і дозволяє уникнути багатьох непорозумінь. Однак прихильники традиційного підходу можуть використовувати числові значення замість булевих. Теоретично, для подання булевої змінної достатньо одного біта. Однак у мові С++ мінімальною одиницею, що має адресу, є байт. Тому розмір таких змінних дорівнює 1 байт.

Цілі числа ред.

Колись люди винайшли натуральні числа. З їхньою допомогою люди перелічують предмети і привласнюють їм порядкові номери. Потім, у міру розвитку товарно-грошових стосунків, люди стали робити борги і зрозуміли, що додатних чисел явно недостатньо, і придумали від’ємні (Брахмагупта, близько 628 р.). Тому зовсім не дивно, що найбільш розповсюдженим елементарним числовим типом є ціле число (int). З програмістської точки зору цілі числа являють собою набір бітів, до того ж один з бітів (як правило, старший) задає знак (0 означає додатне число, а 1 — від’ємне). Цілі типи даних є зовсім природними і підтримуються комп'ютером на апаратному рівні. Для представлення негативних цілих чисел використовується або додатковий, або зворотний двійковий код. Додатковий код негативного цілого числа в двійковій системі утворюється шляхом логічного доповнення додатного числа (усі біти заміняються протилежними) і додавання до нього одиниці. При зворотному записі від’ємне значення цілого числа зберігається як логічне доповнення до його абсолютного значення. Точне подання цілого числа залежить від конкретного комп'ютера й операційної системи. Якщо заздалегідь відомо, що деяка цілочисельна величина є тільки додатною, не варто витрачати окремий біт для індикації знаку. Це вдвічі збільшує діапазон зміни числа. Для того щоб подати ціле число без знаку, використовується модифікатор unsigned. Для симетрії в мові С++ передбачений і модифікатор signed, але оскільки всі цілочисельні змінні за замовчуванням мають знак, це ключове слово практично не вживається. Цілі числа зі знаком змінюються від –32768 до 32767. Цілі числа без знака змінюються від 0 до 65535. Оскільки символ у мові С++ задається у вигляді коду, він практично нічим не відрізняється від цілого числа, щоправда, у силу невеликого розміру діапазон його зміни дуже вузький. Наприклад, модифікований тип signed char дозволяє подати цілі числа від –128 до 127. Але ж код не може бути від’ємним, отже, 128 від’ємних чисел витрачаються даремно! Щоб виправити ситуацію і заодно розширити діапазон припустимих символів, у мові передбачений модифікований тип unsigned char. Символи без знаків кодуються числами від 0 до 255, як правило, цього достатньо. Крім того, цілі числа можна модифікувати за допомогою ключових слів short і long. За замовчуванням модифікатор short еквівалентний типу int. Набагато кориснішим виявився модифікатор long, що дозволяє розширити діапазон зміни цілих чисел більш ніж у 30 000 разів: від –2147483648 до 2147483647. Скориставшись модифікатором unsigned, можна подати цілі числа від 0 до 4294967295. За замовчуванням усі цілі чи, як їх ще називають, інтегральні типи мають знак, і тому модифікатор signed практично не застосовується. Цілі числа володіють однією неприємною особливістю. Оскільки їм виділяється фіксований обсяг пам'яті, вони можуть переповняти його. Особливо це стосується типів char і int, що мають щодо невеликий діапазон.

Специфікатори збереження[3] ред.

У залежності від виду зв'язування змінні в мові С++ підрозділяються на чотири категорії: статичні, автоматичні, динамічні і зовнішні.

Статичні змінні ред.

Статичними називаються змінні, які зв'язуються з коміркою пам'яті на етапі компіляції і залишаються зв'язаними з нею аж до припинення виконання програми. Статичні змінні часто виявляються корисними. Яскравим прикладом є глобальні змінні, котрі доступні в будь-якій точці програми і, отже, повинні бути зв'язані з однією і тією ж коміркою протягом усього часу виконання програми. Крім того, іноді буває зручно, щоб змінні, що оголошуються усередині функцій, зберігали своє значення між окремими викликами. У цьому випадку також необхідно, щоб статична змінна не змінювала адреси. Ще однією перевагою статичних змінних є їхня ефективність. Статичні змінні допускають пряму адресацію, тоді як динамічні вимагають більш повільної непрямої адресації за допомогою вказівників і посилань. Крім того, створення і видалення статичних змінних не вимагає додаткових витрат часу. Однак статичне зв'язування обмежує гнучкість програм. Зокрема, якби мова С++ містила лише статичні змінні, рекурсивні функції виявилися б неможливими. Для того щоб оголосити статичну змінну, у мові C++ використовується специфікатор static. Врахуйте, що це слово в мові С++ багатозначне. По-перше, воно є спадщиною мови С й означає змінні, що зберігають свої значення між окремими викликами функціями. По-друге, цим ключовим словом позначають особливі члени класів, що належать відразу всім його об'єктам і жодному окремо. Таким чином, зміст специфікатора static залежить від його контексту. Статичні змінні розділяються на локальні і глобальні. Локальна статична змінна, як і глобальна, не змінює адреси при виконанні програми. Однак локальна статична змінна, на відміну від глобальної, доступна лише усередині свого блоку чи функції, зберігаючи свої значення між викликами функції.

Автоматичні змінні ред.

Автоматичними називаються змінні, які з коміркою зв'язуються динамічно, тобто під час виконання операторів оголошення, а з типом — статично. Такі змінні іменуються автоматичними, тому що вони створюються і знищуються без утручання програміста. У мові C++ усі локальні змінні за замовчуванням є автоматичними. За винятком адреси, всі атрибути автоматичних змінних зв'язуються статично. Виключення складають об'єднання, що у різні моменти часу можуть містити змінні різних типів і, отже, зв'язуються з типом динамічно. Мова С++ містить ключове слово auto, яке можна використовувати для оголошення локальних змінних. Оскільки усі локальні змінні за замовчуванням вважаються автоматичними, це ключове слово вказувати необов'язково. Автоматичні змінні є антиподами статичних. Вони виникають при вході в блок чи функцію, у якій вони описані, і знищуються при виході з неї. Таким чином, якщо при оголошенні автоматична змінна ініціалізується деяким значенням, це буде відбуватися заново при кожнім виклику функції. На противагу цьому ініціалізація статичної змінної відбувається лише один раз, і при наступних викликах функції оператор оголошення буде зігнорований. Підкреслимо, що це стосується лише оголошення статичної змінної. Якщо її початкове значення задається за допомогою звичайного оператора присвоювання, він буде виконуватися при кожнім виклику функції.

Динамічні змінні ред.

Динамічні змінні не мають імен. Вони розташовуються в динамічній пам'яті, чи купі, і видаляються з неї під час виконання програми. Для звертання до цих змінних потрібні особливі засоби: вказівники і посилання. Динамічні змінні створюються або оператором new, або стандартною функцією (malloc(), calloc() чи realloc()). Знищення динамічних змінних здійснюється оператором delete (після того, як пам’ять була виділена оператором new) чи функцією free() (при використанні разом з ним функцій malloc() , calloc() чи realloc()). Оператор виділення пам'яті new як операнд використовує ім'я типу. Результатом цього оператора є вказівник на адресу динамічної області пам’яті, що має тип операнда. Динамічна змінна зв'язується з типом під час іляції, тому це зв'язування є статичним. Втім, динамічні змінні зв'язуються з виділеною областю пам'яті в ході виконання програми, тому цей вид зв'язування є динамічним.

Реєстрові змінні ред.

Специфікатор register дозволяє зберігати значення змінної в регістрі центрального процесора, а не в пам'яті. Це набагато підвищує швидкість виконання операцій над цією змінною. Чи зберігати змінну в регістрі, компілятор вирішує сам. Отже, це навіть не інструкція, а просто рекомендація, що впливає на процес оптимізації коду. У регістрах центрального процесора, як правило, зберігаються символи і цілі числа, що інтенсивно використовуються програмою. Яскравим прикладом такої змінної є лічильник циклу. Специфікатор register можна застосовувати тільки до локальних змінних і формальних параметрів функцій. До глобальних змінних він не застосовується. Як відомо, у мові С неможливо обчислити адреса реєстрової змінної за допомогою оператора &, оскільки реєстрові змінні зберігаються, як правило, у процесорі, а його пам'ять не адресується. У той же час у С++ обчислення адреси реєстрової змінної допускається.

Примітки ред.

  1. Х.М. Дейтел, П.Дж. Дейтел "КАК ПРОГРАММИРОВАТЬ НА C++" пятое издание
  2. 1.Х.М. Дейтел, П.Дж. Дейтел "КАК ПРОГРАММИРОВАТЬ НА C++" пятое издание 2.С.Пратта "Язик програмирования С++"
  3. .С.Пратта "Язик програмирования С++"