
- •12. Класи пам'яті даних 100
- •13. Робота з файлами 106
- •14. Посилання 111
- •Склад мови
- •Алфавіт мови
- •Лексеми
- •Ключові слова
- •Ідентифікатори
- •Константи
- •Символьні рядки
- •Знаки операцій, роздільники, коментарі
- •Типи даних
- •Класифікація типів даних
- •Цілочислові типи
- •Дійсні типи
- •Оголошення змінних і констант
- •Переліки
- •Структура програми
- •Функція main
- •Область дії змінної
- •Введення і виведення даних
- •Функції стандартної математичної бібліотеки
- •Вирази і операції
- •Поняття виразу, операнда, операції
- •Порядок виконання операцій
- •Арифметичні операції
- •Порозрядні операції
- •Операції порівняння
- •Логічні операції
- •Операції присвоєння
- •Умовна операція
- •Операція визначення розміру sizeof
- •Узгодження типів у виразах
- •Умовні оператори
- •Оператори
- •Умовний оператор if
- •Оператор вибору switch
- •Оператори циклу
- •Цикл з параметром. Оператор for
- •Цикл з передумовою. Оператор while
- •Цикл з постумовою. Оператор do while
- •Оператори переходу
- •Використання псевдовипадкових чисел
- •Одновимірні масиви
- •Багатовимірні масиви
- •Символьні рядки
- •Вказівники
- •Оголошення вказівника, операції, пов’язані з вказівниками
- •Адресна арифметика
- •Void – вказівники, типізація вказівників
- •Звертання до елементів масивів через вказівники
- •Масиви символьних рядків і масиви вказівників
- •Динамічне виділення пам’яті
- •Структури і об’єднання
- •Оголошення і ініціалізація структур
- •Звертання до елементів структур
- •Перейменування типів
- •Об’єднання
- •Поля бітів
- •Директиви препроцесора
- •Призначення директив препроцесора
- •Директива включення #include
- •Директиви макропідстановок #define I #undef
- •Директиви умовної компіляції
- •Директиви #ifdef, #ifndef
- •Функції
- •Структура функції
- •Виклик функцій. Прототипи функцій
- •Взаємодія фактичних і формальних параметрів функцій
- •Inline – функції
- •Масиви і символьні рядки як параметри функцій
- •Використання кваліфікатора const в оголошеннях параметрів
- •Багатовимірні масиви як параметри функцій
- •Опрацювання структур у функціях
- •Вказівники на функції
- •Рекурсивні функції
- •Класи пам'яті даних
- •Клас пам'яті, час існування і видимість об’єкта
- •Область дії глобальних і локальних змінних
- •Специфікатори класів пам'яті
- •Специфікатори глобальних змінних
- •Багатофайлові програми
- •Робота з файлами
- •Звертання до файлів
- •Послідовний запис до файлу і послідовне читання з файлу
- •Файли з довільним доступом
- •Посилання
- •Призначення посилань
- •Передача аргументів функцій як посилань
Символьні рядки
Мова С++ не спеціального типу для оголошення символьних рядків, символьний рядок розглядається як особливий вид масиву символів. Елементи масиву мають тип char, значеннями є коди символів. Останнім символом рядка має бути нуль-символ (‘\0’), код якого дорівнює нулю. При оголошенні рядки можна ініціалізувати рядковими константами (записуються в подвійних лапках), при цьому останній нуль-символ додається автоматично. Якщо розмір масиву не заданий, для нього виділяється на один елемент більше кількості символів в рядку. Додатковий (останній) елемент зберігає нульовий символ – ознаку кінця рядка.
Створимо два рядка символів, виведемо їх на екран, знайдемо кількість символів в них.
#include <iostream>
#include <ctime>
using namespace std;
int main() {
srand( unsigned( time( NULL ) ) );
char s1[ 20 ] = "Hello s1";
char s2[ ] = "Hello s2";
int i;
for ( i = 0; s1[ i ]; i++ )
cout << s1[ i ];
cout << endl;
i = 0;
while ( s2[ i ] )
cout << s2[ i++ ];
cout << endl;
// Кількість символів в рядку 1 i 2
i = 0;
while ( s1[ ++i ] ) ;
cout << i << endl;
i = 0;
while ( s2[ ++i ] ) ;
cout << i << endl;
}
Вказівники
Оголошення вказівника, операції, пов’язані з вказівниками
Вказівник (покажчик, англ. pointer) – це особливий тип даних, значенням якого є адреса певного байта оперативної пам'яті. Найчастіше вказівник зберігає адресу першого байта одного з об’єктів програми. Це називається посиланням на вказаний об’єкт.
Вказівники можуть бути константними і змінними: константні вказівники зберігають незмінну адресу оперативної пам'яті, зокрема константними вказівниками є імена масивів і символьних рядків; вказівники – змінні є змінними програми, їм можна надавати значення адрес різних ділянок оперативної пам'яті.
Як і для змінних, вказівники необхідно оголошувати. Синтаксис оголошення змінних такий:
базовий_тип * ім’я_вказівника;
тут базовий тип – тип об’єктів програми, адреси яких може зберігати даний вказівник; це може бути довільний стандартний тип або тип користувача; * - ознака того, що наступна змінна є вказівником; ім’я вказівника – ідентифікатор.
З вказівниками пов’язані дві унарні операції: & - визначення адреси, * - звертання до об’єкта за адресою.
Значенням операції визначення адреси змінної є адреса операнда (тобто змінної), перед яким стоїть знак &. Розглянемо фрагмент програми:
#include <iostream>
using namespace std;
int main() {
int a = 5, *pa;
pa = &a;
cout << pa << endl;
}
тут змінна а – звичайна змінна цілого типу, ра – вказівник на ціле. В результаті виконання рядка pa = &a; змінна ра буде містити адресу першого байти пам'яті, яку займає змінна а.
Значення адреси змінної можна присвоїти тим вказівникам, базовий тип яких збігається з типом змінної. Тобто, спроба компіляції наступної програми буде призводити до помилки:
#include <iostream>
using namespace std;
int main() {
int a = 5, *pa;
char c = 'z';
pa = &c; // Помилка, базовий тип вказівника і
// тип змінної не співпадають
}
Існують такі обмеження щодо застосування операції визначення адреси: не можна визначати адресу константи; не можна визначати адресу виразу; не можна визначати адресу змінної з класом пам'яті register.
В оголошенні вказівника можна виконувати ініціалізацію значенням адреси об’єкта, що має відповідний до вказівника тип і був оголошений раніше. Наприклад:
int a = 5, *pa = &a;
Вказівники можна також ініціалізувати значеннями адрес – констант:
char *pc = (char *) 0x04cd;
Існує константа NULL, яку можна присвоювати вказівникам всіх типів. Вважається що вказівник, значенням якого є NULL, не посилається на жоден об’єкт програми. Такий вказівник називають порожнім вказівником.
Операндом операції звертання за адресою є вказівник або адреса ділянки пам'яті, а результатом – значення об’єкта, який зберігається в цій ділянці. Цю операцію також називають розадресацією, вона є зворотною до операції взяття адреси. Результат цієї операції має тип, що був заданий як базовий в оголошенні вказівника. Звертання через вказівник можна використовувати всюди, де синтаксично може бути записаний об’єкт даного типу. Наприклад:
#include <iostream>
using namespace std;
int main() {
int a = 5, *pa;
pa = &a; // Отримали адресу змінної а
*pa = 12; // Змінили значення змінної а
cout << *pa << endl;
cout << a << endl;
}
В оголошеннях вказівників можна вказувати кваліфікатор const. Роль цього кваліфікатора визначається місцем його запису.
Якщо кваліфікатор const в оголошенні передує базовому типу вказівника, то він означає, що за допомогою такого вказівника заборонено змінювати значення об’єкта, на який він посилається.
#include <iostream>
using namespace std;
int main() {
int a = 5;
const int b = 123;
const int * cp;
cp = &a; // Можна змінювати значення вказівника
*cp = 12; // Помилка, не можна змінювати значення
// об’єкта, на який посилається вказ-к
cp = &b;
cout << *cp << endl; // Можна читати значення об’єкта, на
// який посилається вказівник
}
Якщо кваліфікатор const в оголошенні передує імені вказівника, то такий вказівник буде константним. В оголошенні константний вказівник обов’язково необхідно проініціалізувати, змінювати це значення не можна.
#include <iostream>
using namespace std;
int main() {
int a = 5, b = 12;
int * const cp = &a;
cp = &b; // Помилка, не можна змінювати значення
// константного вказівника
*cp = 12; // Можна змінювати значення об’єкта, на
// який посилається вказівник
cout << *cp << endl; // Можна читати значення об’єкта, на
// який посилається вказівник
}