МОВА ПРОГРАМУВАННЯ СІ ДЛЯ ПЕРСОНАЛЬНОГО КОМП’ЮТЕРА Вступ Історична довідка Мова Сі була розроблена в США співробітниками фірми BellLaboratories на рубежі 70-х років. Тобто це відносно стара мова. Початкова реалізація Сі була виконана для ЕОМ PDP-11 фірми DEC (CM-3). Приблизно в той же час Сі була використана для розробки операційної системи UNIX. Перший опис мови Сі був даний авторами Б.Керніганом і Д.Річі [1]. На жаль, він не відзначався строгістю та повнотою, і містив ряд моментів, що допускали неоднозначне тлумачення. Тому наступні розробники систем програмування трактували мову Сі по різному. На протязі тривалого часу фактичним стандартом мови являлася його реалізація в сьомій версії ОС UNIX, однак заяви про сумісність деякої системи програмування з реалізацією мови Сі в ОС UNIX, як правило, не означали точної відповідності. На даний момент число найбільш поширених реалізацій Сі становить кілька десятків. Але всі вони, по суті, підтримують різні діалекти мови Сі. Для виправлення цієї ситуації в 1983р. при Американському Національному Інституті Стандартів (ANSI) було створено комітет по стандартизації мови Сі. В 1986р. розроблений цим комітетом проект був оприлюднений для широкого обговорення. В 1989р. кінцевий варіант проекту був затверджений в якості стандарта ANSI. Треба відмітити, що хоча переважна більшість реалізацій мови Сі, що зараз використовуються, не підтримує стандарт ANSI у повному обсязі, існує тенденція до створення нових реалізацій мови Сі, що відповідають стандарту ANSI. На наших теренах найбільшого поширення набули системи програмування фірми Microsoft i Borland Internation. Коротка характеристика мови Сі 1. Мова Сі універсальна, однак найбільш ефективне її застосування в задачах системного програмування – розробці трансляторів, операційних систем, екранних інтерфейсів, інструментальних засобів. 2. Мова Сі добре себе зарекомендувала ефективністю, економним записом алгоритмів, логічною стрункістю програм. В багатьох випадках програми, написані на Сі, по швидкості наближаються до асемблерних програм, при цьому вони більш наочні та прості у супроводі. 3. Одною з основних переваг мови Сі вважається висока переносимість написаних на ній програм між комп’ютерами з різною архітектурою, між різними операційними середовищами. Транслятори мови Сі існують практично для всіх ПК, що зараз використовуються. При створенні Сі була поставлена ціль – забезпечити програміста зручною інструментальною мовою, яка б могла замінити мову асемблера. В результаті з’явилася мова програмування високого рівня, що забезпечує незвичайно легкий доступ до апаратних засобів комп’ютера. Іноді Сі називають мовою програмування “середнього” рівня. З одного боку, як інші сучасні мови високого рівня мова Сі підтримує повний набір конструкцій структурного програмування, модульність, блочну структуру програм, окрему компіляцію. З іншої сторони, мова Сі має ряд низькорівневих рис. Деякі особливості мови Сі 1. В мові Сі реалізовані деякі операції низького рівня (зокрема, операції над бітами). 2. Базові типи даних мови Сі відображають ті ж об’єкти, з якими мають справу в програмі на мові асемблер, – байти, машинні слова, символи, рядки. 3. Мова Сі підтримує механізм покажчиків на змінні та функції: (Покажчик – це змінна, призначена для зберігання машинної адреси деякої змінної або функції). Підтримується арифметика покажчика, що дозволяє реалізовувати безпосередній доступ і роботу з адресами пам’яті практично з такою ж легкістю, як на мові асемблер. Зауваження ! Робота з покажчиками вимагає особливої уваги. 4. Мова Сі, як ніяка інша мова високого рівня , “довіряє” програмісту. Навіть при перетворені типів даних накладаються незначні обмеження. Слабкий контроль типів може допомогти в підвищенні ефективності програм, але лише при хорошому володінні мовою Сі. В протилежному випадку відладка буде дуже важкою, а надійність створених програм низькою. 5. Враховуючи ефективність і потужність конструкцій мови Сі, вона відносно мала за об’ємом. В ній відсутні вбудовані оператори вводу/виводу, динамічного розміру пам’яті, керування процесами та інші. Однак в системне оточення мови Сі входить бібліотека стандартних функцій, в яких реалізовані подібні дії. Винесення цих функцій в бібліотеку дозволяє відокремити особливості архітектури конкретного комп’ютера і домовленостей операційної системи від реалізації мови, зробити програми максимально незалежними від деталей реалізації операційного середовища. В той же час програмісти можуть користуватися системними бібліотечними програмами, щоб більш ефективно використовувати особливості конкретних операційних середовищ. Частина 1. Опис мови Сі 1. Елементи мови Сі Під елементами мови будемо розуміти її базові конструкції, що використовуються при написанні програм. До елементів мови Сі відносяться : 1) алфавіт; 2) константи; 3) ідентифікатори; 4) ключові слова; 5) коментарі; Компілятор мови Сі сприймає файл, що містить програму Сі, як послідовність текстових рядків. Кожен рядок завершений символом нового рядка (в текстовому редакторі цей символ вставляється при натисканні клавіші ENTER). Компілятор розбиває кожний зі зчитаних рядків на групи символів, що називаються лексеми. Лексема – це одиниця тексту, яка не містить в собі інших лексем. Знаки операцій, константи, ідентифікатори, ключові слова – приклади лексем. Ніякі лексеми, крім символьних рядків, не можуть продовжуватися на наступних рядках тексту програми. Це стосується й вищеназваних лексем. Всередині ідентифікаторів, ключових слів і знаків операцій, що складаються з декількох символів, недопустимі символи пропуску. 1.1 Алфавіт В програмах на мові Сі використовують дві множини символів: множину символів мови Сі та множину символів, що можуть бути представлені як окремий символ на клавіатурі даного ПК. Очевидно, що множина символів мови Сі є підмножиною другої множини. Програма на мові Сі може містити тільки символи з множини символів Сі, однак, всередині символьних рядків, символьних констант і коментарів може бути використаний довільний символ з множини символів, які можуть бути представлені як окремий символ на клавіатурі даного ПК. Зауваження! При виявленні неправильно використаних символів, компілятор Сі видає повідомлення про помилку. 1.1.1. Букви і цифри Множина символів мови С включає великі й малі букви латинського алфавіту і арабські цифри. Зауваження! Компілятор розглядає одну й ту ж велику та малу букву як різні символи. 1.1.2. Символи пропуску Символи пропуску відділяють лексеми одну від другої. До символів пропуску відносяться: пропуск, табуляція, перевід рядка, повернення каретки, нова сторінка, вертикальна табуляція, новий рядок. Символ Ctrl-Z (..!!!...) – індикатор кінця файлу. Він автоматично вставляється текстовим редактором при створенні файлу в його кінець. Компілятор мови Сі завершує обробку файлу з текстом програми при виявленні символу Ctrl-Z. Зауваження! 1. Компілятор мови Сі ігнорує символи пропуску, якщо вони використовуються не як компоненти символьних констант чи символьних рядків. Це дозволяє використовувати стільки символів пропуску, скільки потрібно для підвищення наочності програми. 2.Коментарі розглядаються компілятором мови Сі як пробільні символи. 1.1.3. Розділювачі Розділювачі з множини символів мови Сі застосовуються для різних цілей, від організації тексту програми, до визначення вказівок компілятору мови Сі. До розділювачів відносяться наступні символи : ,–кома; !–знак оклику; .–крапка; |–вертикальна риска; ;–крапка з комою; /– нахилена риска вправо (слеш); :–двокрапка; \–нахилена риска вліво (обернений слеш); ?–знак питання; ~ – гільда; ’–апостроф; _– підкреслення; (–ліва кругла дужка; # –знак номера; )–права кругла дужка; ^ – стрілка вверх; {–ліва фігурна дужка; = – знак рівності; }–права фігурна дужка; + – знак плюс; <–знак “менше”; * – знак множення(зірочка); >–знак “більше”; [–ліва квадратна дужка; ]–права квадратна дужка; 1.1.4 Спеціальні символи. Спеціальні символи призначені для представлення символів пропуску і неграфічних символів в рядках та символьних константах. Звичайно вони використовуються для специфікацій таких дій, як повернення каретки і табуляція для терміналів і принтерів, а також для представлення символів, що мають особливий смисл (наприклад, подвійні лапки). Спеціальний символ складається з оберненого слеша за яким слідує буква, або знаки пунктуації, або комбінація цифр. До спеціальних символів відносяться : Спец. символ Шістнадцяткове значення в коді ASCII найменування
\n Ø A Новий рядок
\t Ø q Горизонтальна табуляція
\v Ø B Вертикальна табуляція
\b Ø 8 Забій (повернення на крок)
\r Ø C Повернення каретки
\f Ø Z Нова сторінка(form feed)
\a 2C Звуковий сигнал(alert)
\’ 22 Апостроф(одинарні лапки)
\” 5C Подвійні лапки
\\
Обернений слеш
\ddd
Байтове значення у вісімковому представленні (від 1 до 3 вісімкових цифр)
\xdd
Байтове значення у шістнадцятковому представленні (від 1 до 20 шістнадцяткових цифр)
Зауваження! 1. Якщо обернений слеш передує символу що не входить в наведений список, то обернений слеш ігнорується : \h еквівалентно h 2. Символ обернений слеш використовується також у якості ознаки продовження символьних рядків та препроцесорних макровизначень. Якщо символ нового рядка слідує безпосередньо за оберненим слешем то комбінація “обернений слеш – символ нового рядка” ігнорується і наступний рядок розглядається як продовження попереднього рядка. 1.1.5 Операції Операції – це комбінації символів, що специфікують дії по перетворенню значень. Компілятор мови Сі інтерпретує кожну з цих комбінацій як самостійну лексему. Список операцій наведено нижче. Операції повинні використовуватися так як наведені, без символів пропуску між символами в тих операціях, які представлені декількома символами. Список операцій мови Сі : Операція Найменування Операція Найменування
! Логічне НІ ?: Умовна операція
~ Зворотній код ++ інкремент
+ Додавання; унарний плюс -- Декремент
- Віднімання; унарний мінус = Просте присвоєння
* Множення; Значення за адресою += Присвоєння з додаванням
/ ділення -= Присвоєння з відніманням
% Остача від ділення *= Присвоєння з множенням
<< Зсув вліво /= Присвоєння з діленням
>> Зсув вправо %= Присвоєння з остачею без ділення
< Менше >>= Присвоєння з зсувом вправо
> більше <<= Присвоєння з зсувом вліво
>= Більше чи дорівнює &= Присвоєння порозрядним I
= = дорівнює |= Присвоєння з порозрядним АБО
!= Не дорівнює ^= Присвоєння з порозрядним додаванням за модулем 2
^ Порозрядне додавання за модулем 2 . елемент структури або об’єднання
&& Логічне I > Покажчик на елемент структури
|| Логічне АБО (type) Приведення типу
, Послідовне виконання (кома)
Зауваження! 1. До списку не включена операціяs size of оскільки вона задається ключовим словом а не символом. 2. Умовна операція ?: не являється двосимвольною, а тернарною (трьохоперандною операцією) і має формат <операнд1>?<операнд2>:<операнд3>. Константа – це число, символ чи рядок символів. Константи застосовують для задання сталих величин і поділяють на чотири типи: а) цілі; б) з плаваючою крапкою; в) символьні; г) символьні рядки. 1.2.1. Цілі константи Ціла константа – це десяткове, вісімкове чи шістнадцяткове число, що являє собою ціле значення. Формат представлення цілої константи : а) десяткової <цифри>, цифри – послідовність з однієї чи більш десяткових цифр від 0 до 9. б) вісімкової 0 <вісімкові_цифри>, вісімкові цифри – послідовність з однієї чи більше вісімкових цифр від 0 до 7. Зауваження! Запис 0 спереду у вісімковій константі обов’язковий. в) шістнадцяткова 0х <шістнадцяткові_цифри>, цифра це – послідовність з однієї чи більше шістнадцяткових цифр від 0 до F! Зауваження! -шістнадцяткова цифра – цифра від 0 до 9., або букви а|A, b|B, c|C, d|D, e|E, f|F. - допускається “суміш” великих та малих літер. 0х – обов’язковий. Навести приклади 1010 = 0128 = 0хa16 = 0хA16 13210 = 02048= 0х8416 Зауваження! 1) Символи пропуску у цілих константах недопустимі. 2) Цілі константи завжди специфікують додатні значення. Якщо потрібно від’ємне значення, то формується константний вираз зі знака мінус і константи після нього. Знак мінус розглядається при цьому як арифметична операція. Діапазон значень цілих констант для різних типів і тип констант розглядається після розділу п.3.1. , 3.2. Від’ємні константи – лише десяткові. 1.1.2. Константи з плаваючою крапкою Константа з плаваючою крапкою – це дійсне десяткове додатне число, що включає цілу частину, дробову частину та експоненту. Формат представлення константи з плаваючою комою : [<цифри>][.<цифри>][<експ>[-]<цифри>] <цифри> – одна чи більше десяткових цифр від 0 до 9. <експ>] – ознака експоненти, що задається символами Е або е. Зауваження! 1) Не можна одночасно опустити: а) цілу та дробову частину; б) десяткову крапку з дробовою частиною і експоненту. 2) Між цифрами чи символами константи символи пропуску недопустимі. 3) Константи з плаваючою крапкою специфікують додатні значення. Якщо потрібно від’ємні значення, то ставлять перед константою знак –, що розглядається як арифметична операція. Приклади : 15.75 1.57Е1 1.57е-2 .75 .0075е2 1.2.3. Символьні константи Символьна константа – це буква, цифра, знак пунктуації чи спеціальний символ, узятий в апострофи. Значення символьної константи рівне коду символа, який нею представляється. Форма представлення символьної константи. ‘<символ>’ де <символ> довільний символ з множини символів, що можуть бути представлені (в тому числі довільним спеціальним символом), за виключенням символів апострофа, оберненого слеша і нового рядка. Апостроф представляється як ‘\’’ Обернений слеш представляється як ‘\\’’ Символ нового рядка представляється як ‘\n’ Приклади: ‘a’ , ‘b\’ –забій \x1В – Esc в коді ASCII Тип символьних констант розглядається після розгляду п.3.1.,3.2. 1.2.4. Символьні рядки Символьний рядок – це послідовність символів в подвійних лапках. Символьний рядок розглядається як масив символів, кожен елемент якого представляє окремий символ. Форма представлення символьного рядка. “<символи>” де <символи> – довільна (в тому числі і нульова) кількість символів з множини символів, що можуть бути представлені, за виключенням символів подвійні лапки, обернений слеш, новий рядок, які представляються в рядку спеціальними символами. Приклади : 1) “розбиття рядка\ MSC5.0 TC на частини“ 2) “розбиття рядка“ “на частини“ Кожен символ символьного рядка зберігається в окремому байті оперативної пам’яті. Ознакою кінця рядка являється нульовий символ ‘\0‘, що автоматично додається в якості останнього байта символьного рядка. Кожен символьний рядок в програмі розглядається як окремий об’єкт: дві ідентичні стрічки займають дві різні області пам’яті. В ТС реалізована опція компіляції, що дозволяє зберігати у пам’яті тільки одну з ідентичних стрічок. Тип символьної стрічки розглядається після розгляду п.3.1.,3.2.,3.3.1. 1.3. Ідентифікатори Ідентифікатори – це імена змінних, функцій та міток, що використовуються в програмі. Ідентифікатор вводиться в оголошенні змінної чи функції, або в якості мітки оператора. Після цього його можна застосовувати в наступних операторах програми. Ідентифікатор – це послідовність з одної чи більше латинських букв, цифр та символа підкреслення, яка починається з букви чи символа підкреслення. Допускається довільне число символів в ідентифікаторі, але тільки перші 32 символа розглядаються компілятором мови Сі як значущі. (Пояснити на прикладі). Приклади ідентифікаторів : Abc temp temp1 top_of_page GetCursorType Зауваження! 1) Компілятор мови Сі розглядає букви верхнього та нижнього рядка як різні символи. Тому кожен з ідентифікаторів abc, ABC, Abc, aBC – являється унікальним. 2) Компілятор мови Сі не допускає використання ідентифікаторів, що збігаються по правопису з ключовими словами. Наприклад, ідентифікатор while – недопустимий, однак ідентифікатор While – допустимий. Не рекомендується застосовувати ідентифікатори що відрізняються від ключових слів та імен бібліотечних функцій тільки регістром букв. 1.4. Ключові слова Ключові слова – це наперед визначені ідентифікатори, що мають спеціальні позначення для компілятора мови Сі. Імена об’єктів програми не можуть співпадати з ключовими словами. Список ключових слів (набір ключових слів з кожною новою версією системи програмування може поповнюватись) auto continue else for long signed switch void break default enum goto register sizeof typedef while case do extern if return static union char double float inf short struel unsigned 1.5. Коментарі Коментарі – це послідовність символів, яка сприймається компілятором мови Сі як окремий символ пропуску і ігнорується. Синтаксис коментаря /*<символи>*/ , де <символи> повинні належати множині символів, що можуть бути представлені на даному ПК. Зауваження! 1) Всередині коментаря допустимий символ нового рядка. Це значить, що коментарі можуть займати більше одного рядка програми. 2) Всередині коментаря недопустима комбінація символів */ .Це означає, що коментарі не можуть бити вкладеними. 3) Коментар можна застосувати всюди де можна застосувати символи пропуску. Навести приклади коментаря на один рядок, на декілька рядків, коментарі з помилками (наприклад, з включенням символів */. Дати рекомендації по застосуванню коментарів 2. Структура програми 2.1. Вихідна програма Вихідна програма являє собою сукупність наступних елементів: а) директив препроцесора; б) вказівок компілятору; в) оголошень та визначень. а) директиви препроцесора – задають дії препроцесора по перетворенню тексту програми перед компіляцією; б) вказівок компілятору – спеціальні інструкції згідно з якими компілятор веде компіляцію; в) 1. оголошення змінної – задає ім’я та атрибути змінної. 2. визначення змінної – призводить до виділення пам’яті для змінної і задає (явно чи неявно) її початкове значення . 3. оголошення функції – задає її ім’я, тип значення, що повертається і може задавати атрибути її формальних параметрів. 4. визначення функції – задає тіло функції, що являє собою складений оператор (блок), що містить оголошення і оператори. Також задає ім’я функції, тип значення, що повертається та атрибути її формальних параметрів. 5. оголошення типу – дозволяє створити власний тип. Полягає в присвоєнні імені деякому базовому чи складеному типу мови Сі. Зауваження! Для типу поняття оголошення та визначення співпадають. Зауваження! 1) Вихідна програма може містити довільне число директив, вказівок компілятору, оголошень та визначень. 2) Порядок появи цих елементів в програмі має суттєве значення. 3) Для того, щоб програма на мові Сі могла бути скомпільована та виконана, вона повинна містити по крайній мірі одне визначення – визначення функції. Якщо програма містить декілька функцій, то серед них виділяється одна функція, яка повинна мати ім’я main. З неї починається виконання програми. Якщо програма містить тільки одну функцію, то вона і являється головною і повинна мати ім’я main. Порядок визначень функції у вихідній програмі не є істотним. 2.2.Вихідні файли Текст програми на мові Сі може бути розбитий на декілька вихідних файлів. Вихідний файл являє собою текстовий файл, що містить або всю програму, або її частину. Для створення програми кожний з вихідних файлів, що входить до її складу, повинен бути скомпільований окремо, а потім зв’язаний з іншими файлами редактором зв’язків. Можна окремі вихідні файли об’єднувати в один вихідний файл, який компілюється як одне ціле, за допомогою директиви # include. Вихідний файл може містити довільну цілісну комбінацію директив, вказівок компілятору, оголошень та визначень. Під цілісністю розуміється, що такі об’єкти, як, наприклад, визначення функції, повинні розміщуватися в одному файлі, тобто не можуть починатися в одному файлі, а закінчуватися в іншому. Зауваження! 1) Вихідний файл не обов’язково повинен містити оператори, що виконуються. Він може містити тільки визначення змінних. Приклад: /*Перший вихідний файл.(функція main) */ extern int max(int x, int y); /*оголошення функції*/ void main (void) { int a=1; int b=2; int z -; z = max(x,y); } /*другий вихідний файл */ int max (int x, int y ) { if (x>b) return x; else return y; } 2.3. Виконання програми. (РОЗДІЛ ОПУЩЕНО) 2.4. Час життя та область дії. Дуже важливим для розуміння структури програми на мові Сі являється поняття “час життя” та “область дії”. Час життя змінної може бути “глобальним” чи “локальним”. 1) Об’єкт з глобальним часом життя характеризується тим, що на протязі всього часу виконання програми з ним асоційована комірка оперативної пам’яті та значення. 2) Об’єкту з локальним часом життя виділяється нова комірка пам’яті при кожному вході в блок, в якому він оголошений чи визначений. Коли виконання блоку завершується, пам’ять, виділена під локальний об’єкт, звільняється і локальний об’єкт втрачає своє значення. Блок – складений оператор. Тіло функції – блок. Блоки в свою чергу можуть містити всередині себе інші, вкладені блоки. З цього випливає, що функції мають блочну структуру. Однак, функції не можуть бути вкладеними, тобто визначення функції не може міститися всередині визначення іншої функції. Внутрішні та зовнішні оголошення та визначення: 1) Оголошення та визначення, записані всередині будь-якого блока називаються внутрішніми (на внутрішньому рівні). 2) Оголошення та визначення, записані поза межами усіх блоків називаються зовнішніми (на зовнішньому рівні). Змінні та функції можуть бути проголошені як на зовнішньому, так і на внутрішньому рівнях. Змінні визначаються на внутрішньому і зовнішньому рівнях, а функції тільки на зовнішньому. Всі функції мають глобальний час життя. Змінні, визначені на зовнішньому рівні, завжди мають глобальний час життя. Змінні, визначені на внутрішньому рівні, мають локальний час життя, однак шляхом вказування для них специфікації класа пам’яті static можна зробити їх час життя глобальним. Область дії об’єкта визначає, в яких ділянках програми допустимо використовувати ім’я цього об’єкта. Наприклад, об’єкт з глобальним часом життя існує на протязі всього часу виконання програми, однак він доступний тільки в тих частинах програми, на які поширюється його область дії. Об’єкт може мати глобальну чи локальну область дії. Глобальна область дії означає, що об’єкт доступний, чи може через відповідні оголошення бути зроблений доступним в межах всіх вихідних файлів, що утворюють програму. Локальна область дії означає, що об’єкт доступний тільки в тому блоці чи файлі, в якому він оголошений чи визначений. Область дії змінної, оголошеної на зовнішньому рівні, поширюється від точки програми, в якій вона оголошена, до кінця вихідного файлу, на всі функції і вкладені блоки, за виключенням випадків локального переоголошення. Область дії змінної, оголошеної на внутрішньому рівні, поширюється від точки програми в якій вона оголошена, до кінця блоку, що містить її оголошення. Така змінна називається локальною. Якщо змінна, оголошена всередині блоку, має те ж саме ім’я, що і змінна, оголошена на зовнішньому рівні, то внутрішнє оголошення змінної заміняє (витісняє) в межах блоку зовнішнє оголошення. Цей механізм називається локальним переоголошенням змінної. Область дії змінної зовнішнього рівня відновлюється при завершенні блоку. Блок, вкладений в інший блок, може в свою чергу містити локальні переоголошення змінних, оголошених в охоплюючому блоці. Локальне переоголошення змінної має силу у внутрішньому блоці, а дія його початкового оголошення відновлюється, коли керування повертається в охоплюючий блок. Область дії змінної зі зовнішнього (охоплюючого) блоку поширюється на всі внутрішні (вкладені) блоки, за виключенням тих блоків, в яких вона локально переоголошуюється. Область дії типів, що створені програмістом, підлягає тим самим правилам, що й область дії змінних. Особливості використання функцій в мові Сі: На внутрішньому рівні функція може бути тільки оголошена, а на зовнішньому рівні і оголошена і визначена. Для роботи зі змінною її необхідно попередньо явно оголосити, а для того, щоб викликати функцію, це необов’язково (виклик функції компілятор мови Сі розглядає як неявне оголошення функції з типом значення що повертається int). Область дії функції (оголошеної з класом пам’яті extern) поширюється на всі вихідні файли програми. Приклад. /* і визначається на зовнішньому рівні */ int і =1 ; */ функція визначена на зовнішньому рівні */ vord main (void) { printf (“%d\n”, i); //друк 1. /* перший вкладений блок */ { /* і перевизначається */ int i=2; printf (“%d/n”, i) ; //друк 2. /* другий вкладений блок */ { /* і перевизначається */ і=3; printf (“%d/n”, i) ; //друк 3. } printf (“%d/n”, i) ; //друк 2 } printf (“%d\n”,i) ; //друк 1 } 2.5.Простір імен В програмі на мові Сі імена (ідентифікатори) використовуються для посилань на різного роду об’єкти-функції, змінні, формальні параметри і т.п. При дотриманні певних правил допускається використання одного й того ж ідентифікатора для більш ніж одного програмного об’єкта. Для того, щоб розрізняти ідентифікатори об’єктів різного роду, компілятор мови Сі встановлює так звані “простори імен”. В межах одного простору імена повинні бути унікальними, однак в різних просторах можуть міститися ідентичні імена. Це значить, що можна використовувати один і той же ідентифікатор для двох чи більше різних об’єктів, якщо імена належать до різних просторів.
Об’єкти Простір імен
Змінні, функції, формальні параметри, елементи списку переліку, typedef (оголошення імен типів) Унікальність імен в межах цього простору тісно пов’язана з поняттям області дії. Це значить, що в даному просторі можуть міститися ідентифікатори, що співпадають, якщо області дії найменованих ними об’єктів не перетинаються. (Співпадіння ідентифікаторів можливе тільки при локальному переоголошенні).
Теги
Елементи структур та об’єднань Елементи кожної структури чи об’єднання створюють свій простір імен, тому ім’я кожного елемента повинно бути унікальним всередині структури чи об’єднання, але не повинно відрізнятися від будь-якого іншого імені в програмі, включаючи імена елементів інших структур та об’єднань.
Мітки операторів Кожна мітка повинна відрізнятися від усіх інших міток операторів в тій самій функції. В різних функціях можуть бути однакові мітки.
3. Оголошення Синтаксис оголошень в мові Сі: < специфікація.класу пам’яті > <специфікація типу > <описувач>[=<ініціалізатор>] [,<описувач> [=<ініціалізатор>…]]; Де: <специфікація типу > – ім’я типу, що присвоюється об’єкту; <описувач> – ідентифікатор простої змінної, чи більш складна конструкція при оголошенні змінної складного типу; <ініціалізатор> – значення, чи послідовність значень, що присвоюється змінній при визначенні. Зауваження! 1. В деяких випадках специфікація класу пам’яті і/або специфікація типу може бути опущена. 2. Всі змінні в мові Сі повинні бути явно проголошенні перед їх застосуванням, за виключенням формальних параметрів, що мають тип int. 3. Функції можуть бити оголошенні явно шляхом задання оголошення чи визначення функції, або неявно, якщо їх виклик робиться до оголошення чи визначення. 4. Специфікація класу пам’яті впливає на то, в якій області пам’яті зберігається об’єкт, що оголошується, чи відбувається його неявна ініціалізація і на які ділянки програми поширюється область його дії. 3.1. Базові типи даних Базові типи Специфікація типів Специфікація типів
цілі signed char (char) signed int (signed, int) signed short int (short, signedr short) signed long int (long, signed long) unsigned char unsigned int (unsigned) unsigned short int (unsigned short) unsigned long int (unsigned long) Знаковий символьний Знаковий цілий Знаковий короткий цілий Знаковий довгий тип Беззнаковий символьний Беззнаковий цілий Беззнаковий короткий цілий Беззнаковий довгий цілий
плаваючі float double long float long double Плаваючий одинарної точності Плаваючий подвійної точності Довгий плаваючий в один.точн. Довгий плаваючий в подв.точн.
інші void enum Пустий Перелічуваний
Зауваження! 1) Не можна оголосити змінну типу void/; 2) по замовчуванню char знаковий тип, однак існує опція (вказівка) компілятора, що дозволяє змінити тип char по замовченню на беззнаковий. 3.2.Область значень. Область значень – це інтервал від мінімального до максимального значень, яке може бути представлене змінною цього типу. Тип Представлення у пам’яті Область значень
сhar 1 байт -128÷127
іnt Залежить від реалізації (2 байта) Залежить від реалізації (-32.768÷32.767)
short 2 байта -32.768÷32.767
long 4 байта -2.147.483.148÷2.147.483.647
unsigned char 1 байт 0÷255
unsigned Залежить від реалізації (2 байта) Залежить від реалізації (0÷15.535)
unsigned short 2 байта 0÷65.535
unsigned long 4 байта 0÷4.294.967.295
float 4 байта Стандартний формат IEEE 3.4*10±38
double 8 байт 1.7 *10±308
До пункту 1.2. константи Діапазон значень констант різних типів (для комп’ютера, на якому int –16 біт, long – 32 біта) Десяткова константа Вісімкова конст. Шістнадцяткова конст. Тип.
0-32767 0- 077777 0× 0- 0×7FFF int
– 0100000 – 177777 0×8000 – 0×FFFF unsigned int
3.2768-2.147.483.097 0200000 – 017777777777 0×10000 – 0×7FFFFFFF long
– 020000000000 – 030000000000 0×8000000 – 0×FFFFFFFF unsigned long
Для довільної константи можна явно визначити тип: l, L –long; u – unsigned; або комбінація u та l. Не завжди можна використати у виразі max та min значення для констант даного типу. Наприклад -32768 типу short -32768>(-) 32768. Значення 32768 завелике для значення short, то воно представляється типом long і константа -32768 буде мати тип long. Для short – явне приведення типу (short) 1-32768. 3.3. Описувачі 3.3.1. Синтаксис описувачів. Синтаксис описувачів задається наступними рекурсивними правилами: <ідентифікатор> <описувач>[ ] <описувач>[<константний вираз>] *<описувач> <описувач>( ) <описувач>(<список типів аргументів>) (<описувач>) Описувачі в мові Сі дозволяють оголосити прості змінні, масиви, покажчики і функції. В найпростішому випадку, якщо оголошується проста змінна числового типу, або структура, або об‘єднання, описувач являє собою ідентифікатор. При цьому об‘єкту присвоюється тип, заданий специфікацією типу. Для оголошення масива значень специфікованого типу, або функції, що повертає значення специфікованого типу, ідентифікатор доповнюється відповідно [ ] (справа), ( ) (справа), * (зліва) [ ] , ( ) , * – ознаки типу масив, типу функція, типу покажчик. Приклади int list [20]; char *сp; double func( ); 3.3.2. Інтерпретація складених описувачів. Складний оператор – це ідентифікатор, доповнений більш ніж однією ознакою типа масив, покажчик або функція. Деякі комбінації ознак недопустимі : функція не може повертати масив чи функцію, недопустимий масив функцій. При інтерпретації складених описувачів спочатку розглядаються квадратні та круглі дужки справа від ідентифікатора. Вони мають однаковий пріоритет і інтерпретуються зліва направо. Після них справа наліво розглядаються зірочки, розміщені зліва від ідентифікатора. Специфікація типу розглядається на останньому кроці, коли описувач вже повністю проінтерпретовано! Для зміни діючого по замовченню порядку інтерпретації описувача можна застосувати всередині нього круглі дужки. Правила інтерпретації складних описувачів (читання “з середини – назовні ”) Почати треба з ідентифікатора і перевірити, чи є справа від нього відкриваючі квадратні чи круглі дужки. Якщо вони є, то проінтерпретувати праву частину описувача. Потім слід перевірити, чи є зліва від ідентифікатора зірочки і якщо вони є, проінтерпретувати ліву частину. Якщо на якомусь етапі інтерпретації справа зустрінеться закриваюча кругла дужка (що використовується для зміни порядку інтерпретації описувача), то необхідно спочатку повністю провести інтерпретацію всередині даної пари круглих дужок, а потім продовжити інтерпретацію справа від закриваючої круглої дужки. На останньому кроці інтерпретується специфікація типу. Приклад char * (* (* var ) ( ) ) [10] ; ^ ^ ^ ^ ^ ^ ^ 7 6 4 2 1 3 5 1.ідентифікатор – це 2.покажчик на 3.функцію яка вертає 4.покажчик на 5.масив з десяти елементів, які являються 6.покажчиками на 7.значення типу char int *var [5] ; –массив покажчиків на int int (* var) [5] ; – покажчик на масив int long * var () – функція, що вертає покажчик на long long (* var) () – покажчик на функцію, що вертає long stuct bоth { int a; char b; } (* var [5]) () ; масив покажчиків на функції, що вертають структуру типу bоth double (*var() ) [3] – функція що вертає покажчик на масив з 3 double union sigh { int x ; unsigned y ; } ** var [5] [5] ; – масив, елем. якого є масивами покажчиків на покажчики на об’єднання типу sigh 8) union sign { Int x ; Unsigned y ; } *(*var[5]) [5] ; масив покажчиків на масив покажчиків на об’єднання типу sigh. 3.4. Оголошення змінних Різновид змінних Вид змінної Пояснення
Прості змінні Скалярна змінна цілого чи плаваючого типу
Змінна перелічувального типу Проста змінна цілого типу, що приймає значення з наперед визначеного набору найменованих значень
Структура Змінна, яка містить сукупність елементів, що можуть мати різні типи
Об’єднання Змінна, яка містить сукупність елементів, які можуть мати різні типи, але займають одну й ту саму область па’мяті.
Масив Змінна, що містить сукупність елементів однакового типу
Позначення Змінна, яка показує на іншу змінну. (містить її адресу)
3.4.1. Оголошення простої змінної Синтаксис <специфікація типу> <ідентифікатор>[,<ідентифікатор>…]; <ідентифікатор> – задає ім’я змінної <специфікація типу> – задає тип змінної. Тип може бути базовим типом, або типом структура, або об’єднання. Якщо <специфікація типу> опущена, вважається тип int. Приклад : int x ; unsigned long reply, flay ; double other; 3.4.2. Оголошення змінної перелічуваного типу Синтаксис (дві форми представлення) : а) enum [<тег>] {<список переліку>}<описувач>[,<описувач>]; б) enum <тег><ідентифікатор>[,<ідентифікатор>…]; (цій формі повинна передувати форма а) за деякими винятками. Оголошення змінної перелічуваного типу задає ім’я змінної і визначає список поіменованих констант, що називається списком переліку. Кожному елементу списку переліку ставиться у відповідність ціле число. Елементи списку мають тип int. Змінна перелічуваного типу (розмір int) може приймати тільки значення зі свого списку переліку. Таким чином, перелічувальний тип являє собою підмножину цілого типу, а значить над об’єктами перелічуваного типу визначені ті ж самі операції, що й над об’єктами цілого типу. <oписувач> – специфікує або змінну перелічуваного типу, або покажчик на значення перелічуваного типу, або масив елементів, перелічуваного типу, або функцію, що вертає значення перелічуваного типу, або більш складний об’єкт, що є комбінацією перерахованих типів. <тег> – ідентифікатор який іменує перелічуваний тип, специфікований заданим списком переліку. <ідентифікатор> – ім‘я змінної перелічуваного типу. <список переліку>– містить одну чи більше конструкцій виду: <ідентифікатор>[=<константний вираз>], які в списку розділяються комами. Кожен ідентифікатор іменує елемент списку переліку. По замовчуванню, якщо не заданий <константний вираз>, першому елементу присвоюється значення 0, наступному 1 і т.д. Елемент списку переліку являється константою. Запис =<константний вираз> змінює послідовність значень по замовчуванню. Елемент, ідентифікатор якого передує цьому запису, приймає значення <константного виразу>, який повинен мати тип int і може бути як від’ємним так і додатнім. Наступний елемент списку отримує значення <константного виразу> +1, якщо тільки його значення не задається явно іншим константним виразом. Зауваження! В списку переліку можуть міститися елементи, яким співставленні однакові значення, однак кожен ідентифікатор в списку повинен бути унікальним. Крім того, ідентифікатор елемента списку переліку повинен відрізнятися від ідентифікаторів елементів решти списків переліку і від інших ідентифікаторів з тією ж областю дії. 3) Тег перелічуваного типу повинен бути відмінним від тегів інших перелічуваних типів, структур та об’єднань з тією ж самою областю дії. Приклади : 1)enum day { SATURDAY, SUNDAY=0, MONDAY,TUESDAY,WEDNESDAY,THURSDAY, FRIDAY }workday; 2)enum day today = WEDNESDAY; 2.4.3. Оголошення структури Структура дозволяє об’єднати в одному об’єкті сукупність значень, які можуть мати різні типи. Однак в мові Сі реалізовано дуже обмежений набір операцій над структурами як єдиним цілим: передача функції в якості аргументу, повернення в якості значення функції отримання адреси. Можна присвоювати одну структуру іншій, якщо вони мають однаковий тег. Синтаксис: а) struct [<тег>]{<список_оголошень_елементів>}<описувач> [,<описувач>…]; б) struct <тег><описувач>[,<описувач>…]; (цій формі повинна передувати форма а) за деякими вийнятками) <описувач> – специфікує або змінну структурного типу, або покажчик на структуру даного типу, або масив структур даного типу, або функцію що вертає структуру даного типу, або більш складний об’єкт, що являється комбінацією перерахованих типів. <список_оголошень_елементів> – послідовність з одного чи більше оголошень змінних (чи бітових полів) Кожна змінна оголошена в цьому списку називається елементом структури. Зауваження! 1) Змінні в списку не можуть містити специфікацій класу пам’яті та ініціалізаторів. 2) Елементи структури можуть мати базовий тип, або бути масивом, покажчиком, об’єднанням або, в свою чергу, структурою. 3) Елемент структури не може бути структурою того ж типу, в якій він міститься, однак він може бути оголошений як покажчик на тип структури, в яку він входить. Це дозволяє створювати зв’язані списки структур. 4) Ідентифікатори елементів структури повинні різнитися між собою. Ідентифікатори елементи різних структур можуть співпадати. 5) В межах однієї області дії тег структурного типу повинен відрізнятися від тегів інших структурних типів, тегів об’єднань та перелічуваних типів. 6) Розміщення елементів структури у пам’яті. Приклади : struct { float x, y ; } complex; struct student { сhar name [20] ; іnt curs ; } struct student прізвище 1, прізвище 2,….;