- •12. Класи пам'яті даних 100
- •13. Робота з файлами 106
- •14. Посилання 111
- •Склад мови
- •Алфавіт мови
- •Лексеми
- •Ключові слова
- •Ідентифікатори
- •Константи
- •Символьні рядки
- •Знаки операцій, роздільники, коментарі
- •Типи даних
- •Класифікація типів даних
- •Цілочислові типи
- •Дійсні типи
- •Оголошення змінних і констант
- •Переліки
- •Структура програми
- •Функція main
- •Область дії змінної
- •Введення і виведення даних
- •Функції стандартної математичної бібліотеки
- •Вирази і операції
- •Поняття виразу, операнда, операції
- •Порядок виконання операцій
- •Арифметичні операції
- •Порозрядні операції
- •Операції порівняння
- •Логічні операції
- •Операції присвоєння
- •Умовна операція
- •Операція визначення розміру sizeof
- •Узгодження типів у виразах
- •Умовні оператори
- •Оператори
- •Умовний оператор if
- •Оператор вибору switch
- •Оператори циклу
- •Цикл з параметром. Оператор for
- •Цикл з передумовою. Оператор while
- •Цикл з постумовою. Оператор do while
- •Оператори переходу
- •Використання псевдовипадкових чисел
- •Одновимірні масиви
- •Багатовимірні масиви
- •Символьні рядки
- •Вказівники
- •Оголошення вказівника, операції, пов’язані з вказівниками
- •Адресна арифметика
- •Void – вказівники, типізація вказівників
- •Звертання до елементів масивів через вказівники
- •Масиви символьних рядків і масиви вказівників
- •Динамічне виділення пам’яті
- •Структури і об’єднання
- •Оголошення і ініціалізація структур
- •Звертання до елементів структур
- •Перейменування типів
- •Об’єднання
- •Поля бітів
- •Директиви препроцесора
- •Призначення директив препроцесора
- •Директива включення #include
- •Директиви макропідстановок #define I #undef
- •Директиви умовної компіляції
- •Директиви #ifdef, #ifndef
- •Функції
- •Структура функції
- •Виклик функцій. Прототипи функцій
- •Взаємодія фактичних і формальних параметрів функцій
- •Inline – функції
- •Масиви і символьні рядки як параметри функцій
- •Використання кваліфікатора const в оголошеннях параметрів
- •Багатовимірні масиви як параметри функцій
- •Опрацювання структур у функціях
- •Вказівники на функції
- •Рекурсивні функції
- •Класи пам'яті даних
- •Клас пам'яті, час існування і видимість об’єкта
- •Область дії глобальних і локальних змінних
- •Специфікатори класів пам'яті
- •Специфікатори глобальних змінних
- •Багатофайлові програми
- •Робота з файлами
- •Звертання до файлів
- •Послідовний запис до файлу і послідовне читання з файлу
- •Файли з довільним доступом
- •Посилання
- •Призначення посилань
- •Передача аргументів функцій як посилань
Використання кваліфікатора const в оголошеннях параметрів
Якщо аргументом функції є адреса деякого фактичного параметра, то така функція оперує безпосередньо з цим параметром і може змінювати його значення. В багатьох випадках така зміна небажана або взагалі недопустима. Щоб захистити значення фактичного параметра від змін, спричинених помилковим записом у тілі функції якихось даних за адресою цього параметра, треба в оголошенні відповідного формального аргументу вказати кваліфікатор const. Компілятор зафіксує кожну спробу запису даних в константний параметр, а також спробу присвоєння адреси цього параметру внутрішньому вказівнику, оголошеному без кваліфікатора const. Крім цього ключове слово const обов’язкове в тих формальних параметрів-вказівників, яким будуть присвоюватись адреси фактичних параметрів, оголошених з кваліфікатором const.
#include "string.h"
#include <iostream>
using namespace std;
void inc1( int * a, int * b) {
*a += *b;
}
void inc2( int * a, const int * b) {
*a += *b;
}
int main() {
const int N = 2;
int x = 1;
inc1( &x, &N );
inc2( &x, &N );
cout << x << endl;
}
При спробі виклику функції inc1 виникає помилка «Типи const int * i int * несумісні».
Якщо формальний параметр-вказівник оголосити з кваліфатором const, записаним безпосередньо перед іменем вказівника, то компілятор стежитиме, щоб у тілі функції значення цього вказівника не змінювалось. Наприклад:
void f1( const int * p ){
int a;
*p = 123; // помилка
p = &a; // помилки немає
}
void f2( int * const p ) {
int a;
*p = 123; // помилки немає
p = &a; // помилка
}
void f3( const int * const p ) {
int a;
*p = 123; // помилка
p = &a; // помилка
cout << *p; // помилки немає
}
Багатовимірні масиви як параметри функцій
Мова С++ розглядає багатовимірні масиви як масиви, елементами яких є підмасиви меншої вимірності. Тому, якщо багатовимірний масив треба передавати в функцію для опрацювання, то відповідний формальний параметр функції має бути вказівником на перший підмасив цього багатовимірного масиву.
Як і у випадку одновимірних масивів, для оголошення формальних параметрів, що відповідають багатовимірним масивам, можна застосовувати дві форми:
тип_елементв ім’я_масиву [ ] [к-сть_елементів_1]…[к-сть_елементів_n]
тип_елементв ( * ім’я_масиву ) [к-сть_елементів_1]…[к-сть_елементів_n]
В обох формах оголошення треба обов’язково вказувати кількість елементів для кожного виміру масиву, крім першого. Багатовимірний масив зберігається в оперативній пам'яті як послідовність підмасивів. Тому для знаходження адреси певного елемента (чи порядкового номеру елемента в масиві) за значенням його індексів треба знати розмірність кожного виміру цього масиву.
Вказівникова форма оголошення параметра, що є багатовимірним масивом, вимагає використання круглих дужок, оскільки операція * має нижчий пріоритет, ніж операція [ ]. Без круглих дужок відповідний параметр буде масивом вказівників на тип_елементів, а не вказівником на підмасив заданого багатовимірного масиву.
Для прикладу використання різних форм звертання до багатовимірних масивів створимо декілька функцій, які будуть заповнювати двовимірний масив випадковими числами, виводити його на екран, та знаходити найбільший елемент цього масиву.
#ifndef ARRAY2D_H
#define ARRAY2D_H
#include <iostream>
using namespace std;
#define NCOLS 4
#define NROWS 3
void array2d_fill( int m[ ][ NCOLS ] ) {
for ( int i = 0; i < NROWS; i++ )
for ( int j = 0; j < NCOLS; j++ )
m[ i ][ j ] = rand( ) % 100;
}
void array2d_print( int ( * m )[ NCOLS ] ) {
int ( * prow )[ NCOLS ], * pelem;
for ( prow = m; prow - m < NROWS; prow++ ) {
for ( pelem = *prow; pelem - *prow < NCOLS; pelem++ )
cout << *pelem << "\t";
cout << endl;
}
}
int array2d_max( int * m ) {
int max = *m;
int num = NCOLS * NROWS;
for ( int i = 0; i < num; i++, m++ )
if ( max < *m )
max = *m;
return max;
}
#endif
#include "array2d.h"
#include <iostream>
using namespace std;
int main() {
int a[ NROWS ][ NCOLS ];
array2d_fill( a );
array2d_print( a );
cout << array2d_max( a[ 0 ] ) << endl;
}
