- •12. Класи пам'яті даних 100
- •13. Робота з файлами 106
- •14. Посилання 111
- •Склад мови
- •Алфавіт мови
- •Лексеми
- •Ключові слова
- •Ідентифікатори
- •Константи
- •Символьні рядки
- •Знаки операцій, роздільники, коментарі
- •Типи даних
- •Класифікація типів даних
- •Цілочислові типи
- •Дійсні типи
- •Оголошення змінних і констант
- •Переліки
- •Структура програми
- •Функція main
- •Область дії змінної
- •Введення і виведення даних
- •Функції стандартної математичної бібліотеки
- •Вирази і операції
- •Поняття виразу, операнда, операції
- •Порядок виконання операцій
- •Арифметичні операції
- •Порозрядні операції
- •Операції порівняння
- •Логічні операції
- •Операції присвоєння
- •Умовна операція
- •Операція визначення розміру sizeof
- •Узгодження типів у виразах
- •Умовні оператори
- •Оператори
- •Умовний оператор if
- •Оператор вибору switch
- •Оператори циклу
- •Цикл з параметром. Оператор for
- •Цикл з передумовою. Оператор while
- •Цикл з постумовою. Оператор do while
- •Оператори переходу
- •Використання псевдовипадкових чисел
- •Одновимірні масиви
- •Багатовимірні масиви
- •Символьні рядки
- •Вказівники
- •Оголошення вказівника, операції, пов’язані з вказівниками
- •Адресна арифметика
- •Void – вказівники, типізація вказівників
- •Звертання до елементів масивів через вказівники
- •Масиви символьних рядків і масиви вказівників
- •Динамічне виділення пам’яті
- •Структури і об’єднання
- •Оголошення і ініціалізація структур
- •Звертання до елементів структур
- •Перейменування типів
- •Об’єднання
- •Поля бітів
- •Директиви препроцесора
- •Призначення директив препроцесора
- •Директива включення #include
- •Директиви макропідстановок #define I #undef
- •Директиви умовної компіляції
- •Директиви #ifdef, #ifndef
- •Функції
- •Структура функції
- •Виклик функцій. Прототипи функцій
- •Взаємодія фактичних і формальних параметрів функцій
- •Inline – функції
- •Масиви і символьні рядки як параметри функцій
- •Використання кваліфікатора const в оголошеннях параметрів
- •Багатовимірні масиви як параметри функцій
- •Опрацювання структур у функціях
- •Вказівники на функції
- •Рекурсивні функції
- •Класи пам'яті даних
- •Клас пам'яті, час існування і видимість об’єкта
- •Область дії глобальних і локальних змінних
- •Специфікатори класів пам'яті
- •Специфікатори глобальних змінних
- •Багатофайлові програми
- •Робота з файлами
- •Звертання до файлів
- •Послідовний запис до файлу і послідовне читання з файлу
- •Файли з довільним доступом
- •Посилання
- •Призначення посилань
- •Передача аргументів функцій як посилань
Директива включення #include
Директива #include призначена для приєднання до програми текстового файлу, ім’я якого задається в цій директиві. Текст файлу вставляється в програму в тому місці, де була записана директива. Директива допускає дві форми запису імен файлів:
#include < ім’я_файлу > // ім’я в кутових дужках
#include “ім’я_файлу ” // ім’я в лапках
Форма запису імені файлу визначає, де відбувається його пошук. Якщо ім’я файлу записане в кутових дужках, то такий файл повинен зберігатись в спеціальному каталозі середовища програмування (цей каталог часто називають INCLUDE) або в іншому визначеному для компілятора каталозі. Якщо ім’я файлу задається в лапках, то більшість компіляторів починають пошук цього файлу починається з поточного активного каталогу. Якщо файл там не знайдено, то пошук продовжується у каталозі, що відповідає варіанту кутових дужок. Здебільшого в кутових дужках вказують імена стандартних заголовних файлів бібліотечних функцій, а в лапках – імена користувацьких файлів, які повинні бути приєднані до даної програми.
Найчастіше в заголовні файли виносять прототипи функцій, шаблони структур, оголошення користувацьких типів, визначення макросів тощо. Сформовані заголовні файли підключають до кожного програмного файлу, що дає змогу автономно компілювати кожен з них. Доцільно також створювати файли включення, в які записувати власні набори функцій, об’єднані за певним призначенням. Файли, що приєднуються директивою #include, можуть містити в своєму тексті інші директиви #include.
Директиви макропідстановок #define I #undef
Директива #define виконує задані заміни (макропідстановки, макрозаміщення, макрозаміни) в тексті програми. Основним призначенням директиви #define є створення іменованих констант (макроконстант) і функціональних макровизначень (макросів) з параметрами.
Для виконання заданих макрозамін у тексті програми використовують директиву #define, що має таку форму:
#define ім’я_макросу текст_заміни
Ім’я макросу записується за правилами запису ідентифікаторів і задає лексему програми, яка має бути замінена вказаним далі текстом заміни. Між іменем макросу та текстом макропідстановки може стояти довільна кількість символів пробілу. Кінець тексту заміни задає символ кінця рядка. Імена макросів часто задають заголовними літерами.
Директиву #define можна використовувати для створення іменованих констант таким чином:
#define ARRAY_SIZE 20
int a[ ARRAY_SIZE ];
Після пре процесорного опрацювання всі рядки символів ARRAY_SIZE, які будуть знайдені в програмі, будуть замінені на текст заміни, тобто на число 20. Такий спосіб створення констант здебільшого використовується в програмах на мові С, в С++ бажано використовувати константи.
В текстах макропідстановок можна використовувати імена макросів, визначених раніше. Наприклад:
#define MIN 10
#define MAX MIN*20
#define RANGE (MAX-MIN)
Макроси з параметрами, які також називають функціональними макровизначеннями або просто макросами, дають змогу здійснювати макропідстановки, подібні до викликів функцій. Формальні параметри, вказані в списку #define, під час препроцесування замінюються фактичними виразами, заданими в звертанні до макросу. Синтаксис макросу з параметрами такий:
#define ім’я_макросу(список_параметрів) вираз_для_заміни
Між іменем макросу і дужкою, за якою записується список параметрів, не повинно бути символів пробілу, інакше список параметрів і дужки навколо нього будуть сприйняті як початок тексту макрозаміни.
Наведемо приклад макросу, що виконує піднесення до куба заданого аргументу:
#include <iostream>
using namespace std;
#define CUBE(x) ((x)*(x)*(x))
int main() {
cout << CUBE(3) << endl;
}
У виразі підстановки макросу кожен з параметрів і весь вираз слід брати в дужки, щоб уникнути можливих помилок у випадках, коли аргументи виклику є виразами, або коли сам макрос є елементом іншого виразу. Наприклад, якби вираз підстановки CUBE(x) був записаний як (x*x*x), то звертання CUBE(а+1) було б замінене помилковим виразом (а+1*а+1*а+1). Якщо опустити зовнішні дужки, то помилковим буде значення виразу 1.0/CUBE(а), оскільки результат підстановки буде мати вигляд 1.0/(а)*(а)*(а).
Переваги використання макросів з параметрами порівняно з функціями: 1) макрос вбудовується в тіло програми на етапі препроцесування, отже під час виконання програми не витрачається час на передавання параметрів і повертання значень, як це відбувається у разі виклику функцій; 2) аргументи, що вказуються в звертанні до макросів, можуть мати довільний тип, який визначає тип всього виразу макропідстановки, в той час, як типи параметрів функції і тип її значення є незмінними і задаються в оголошенні функції.
Операції # i ## розширюють можливості директиви #define. Їх можна використовувати тільки в тексті макропідстановки.
Операція # називається операцією перетворення в стрінг, вона перетворює в символьний рядок аргумент, перед яким записано знак #. Наприклад:
#include <iostream>
using namespace std;
#define OUT(x) cout << #x " = " << x << endl;
int main() {
int a = 123;
OUT( a ); // a = 123
OUT( a + 4 ); // a + 4 = 127
OUT( sin( 3.14 ) ); // sin( 3.14 ) = 0.00159265
}
#x – це символьний рядок, який буде записаний в дужках після імені макросу. За допомогою цієї операції можна легко вивести у рядки виведення імена змінних і вирази.
Операцію ## називають операцією конкатенації або склеювання. Вона призначена для об’єднання (конкатенації) двох лексем в одну нову лексему. В наступному прикладі виконується склеювання ідентифікаторів змінних:
#include <iostream>
using namespace std;
#define OUT(x,y) cout << x << "\t" << y << "\t" << x##y << endl;
int main() {
int a = 2, b = 3, ab = 4;
OUT( a, b ); // 2 3 4
}
При виконанні макросу на екран будуть виведені три числа: значення змінних a, b, ab. В процесі виконання замін у макросі відбулись склеювання лексем x##y, в результаті отримали ідентифікатор ab.
Операції # i ## можна використовувати разом:
#define OUT1(x,y) cout << #x#y << " = " << x##y << endl;
Директива #undef вказує препроцесору про відміну макровизначення, попередньо встановленого через #define. Синтаксис директиви такий:
#undef ім’я_макросу
У частині програми, записаній після #undef, вказаний макрос вважається невизначеним, жодні зміни не виконуються. Директиву #undef можна використовувати для зміни тексту заміни макросу:
#define MAX 100 // МАХ буде замінено на 100
…
#undef MAX // МАХ невизначений
…
#define MAX 200 // МАХ буде замінено на 200
