Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
колок кінцеве..docx
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
50.77 Кб
Скачать

1. Клас пам'яті, час існування та видимість об'єкта

Кожен об’єкт програми (змінна, функція,...) має свій тип і клас пам’яті. Тип визначає обсяг пам’яті для об’єкта і операції, що можуть виконуватись над об’єктом.

Клас пам'яті задає місце розташування об'єкта в оперативній пам'яті та встановлює для нього час існування, тобто час, протягом якого об‘єкт зберігається в оперативній пам‘яті, і область видимості, яка визначає ту частину програми, де можна використовувати цей об‘єкт. На відміну від типу, клас пам’яті можна явно не вказувати, тоді він встановлюється компілятором за місцем оголошення об'єкта.

За часом існування об‘єкти поділяють на три групи:

    • глобальні (або статичні) – існують протягом усього часу виконання програми;

    • локальні – існують лише при виконанні блоку, де вони оголошені;

    • динамічні – час існування змінюється програмою.

Глобальні дані зберігаються в окремій області оперативної пам’яті–сегменті даних. Локальні дані – в області, що називається стеком. Динамічні дані – в області динамічної пам’яті.

За правилами замовчування змінні, описані всередині блоку, та формальні параметри функцій мають локальний час існування. Змінні, описані зовні всіх блоків (між функціями) мають глобальний час існування.( Блоком вважається тіло функції, а також внутрішня група описів у фігурних дужках) Функції в С – програмах можна описувати тільки на зовнішньому рівні, тому всі функції мають

глобальний час існування.

За областю видимості (або областю дії) об‘єкти ділять на три групи:

    • глобальні – видимі в межах усієї програми;

    • частково глобальні – видимі в межах одного програмного файла;

    • локальні – видимі в блоці, де оголошено даний об‘єкт.

Специфікатори застосовують тільки тоді, коли потрібно змінити стандартний клас пам‘яті об‘єкта, інакше він встановлюється за правилами замовчування.

Синтаксис: специфікатор_класу_пам‘яті тип ім‘я_змінн

Модифікатор

застосування

Оласть дії

Час життя

auto

локальне

блок

тимчасовий

register

локальне

блок

тимчасовий

extern

глобальне

блок

тимчасовий

static

Локальне/ глобальне

Блок/файл

постійний

volatile

глобальне

Блок/файл

постійний

Специфікатори локальних змінних:

    • auto - клас за замовчуванням;

    • register - зберігання змінної у регістрі процесора, дає змогу істотно скоротити час звертання до змінних, за відсутності вільних регістрів змінна буде опрацьовуватись як змінна з класом auto; така змінна не має адреси;

    • static - статичні змінні існуються протягом усього часу виконання програми, проте областю їх дії залишається той блок, у якому вони оголошені;

    • extern - змінна є посиланням на глобальну змінну з тим самим іменем і типом, описану далі в тексті програми або в іншому програмному файлі.

Специфікатори глобальних змінних:

    • static - областю дії даної змінної буде частина програми від точки опису до кінця файлу; в інших файлах програми ця змінна недоступна;

    • extern - змінні є посиланнями на відповідні зовнішні змінні та роблять ці змінні видимими (оголошеними) в межах поточного файлу.

    • Voletile – в тих випадках коли потрібно передбачити модифікацію змінної периферійними пристроєм або іншою програмою

2.Автоматичні змінні. Модифікатор auto використовується для опису локальних змінних. Оскільки для локальних змінних він використовується по замовчуванню, то на практиці його частіше всього опускають.

# include

Int main ()

{

auto int myVal= 1;

cout << myVal;

return 0;

}

Модифікатор auto використовується тільки для локальних змінних, які видно в блоці і при виході з блоку такі змінні знищуються.

Регістрові змінні. Модифікатор register дозволяє компілятору намагатись розмістити дану змінну в регістрі процесора . Якщо така спроба закінчується невдало, то змінна веде себе, як локальна змінна типу auto. Розміщення змінних в регістрах оптимізує програмний код по швидкості, так як процесор оперує із змінними, що знаходяться в регістрах значно швидше ніж з пам’яттю, але у зв’язку з тим, що число регістрів процесора обмежено, то і к-сть таких змінних може бути малою. Модифікатор цього типу використовується тільки для локальних змінних.

Якщо програма складається з декількох модулів, то деякі змінні можуть використовуватися для передачі значень з одного файлу в інший. При чому в одному модулі вона об’являється, якглобальна, а у інших із використанням модифікатора extern. Якщо об’ява зовнішньої змінної здійснюється в блоці, то вона є локальною. На відміну від інших цей модифікатор повідомляє, що початкова об’ява здійснювалась в якомусь іншому файлі.

3. Зовнішні змінні функції

Програма на C складається також з набору зовнішніх об'єктів — змінних або функцій. Прикметник «зовнішній» використовується як протиставлення «внутрішньому», який описує аргументи та змінні, визначені всередині функцій. Зовнішні змінні — означені поза межами будь-якої функції і, таким чином, потенційно доступні багатьом функціям. Самі функції завжди залишаються зовнішніми, оскільки C не дозволяє означати функції всередині інших функцій. Стандартно, зовнішні змінні і функції мають одну властивість, що полягає у тому, що всі звертання до них за тим самим ім'ям — навіть з функцій, компільованих окремо — посилаються на ту саму річ.

Оскільки зовнішні змінні доступні глобально, вони служать альтернативою аргументам функцій, і можуть використовуватись для обміну даними між функціями. Будь-яка функція може звернутися до зовнішньої змінної, посилаючись на її ім'я, якщо це ім'я якимось чином оголошено.

Зовнішні змінні також корисні через більшу область дії. Автоматичні змінні являються внутрішніми для функцій; вони з'являються при вході у функцію і зникають при виході з неї. Напротивагу, зовнішні змінні — постійні, а отже утримують значення від одного виклику функції до іншого. Таким чином, якщо дві функції мусять спільно використовувати якісь дані, але жодна з них не викликає іншої, часто найзручніше, щоб спільні дані зберігалися у зовнішніх змінних, замість передачі їх туди-сюди у вигляді аргументів.

4. Статичні змінні багато в чому подібні на глобальні змінні. Вони використовують модифікатор static. Якщо така змінна об`явлена глобально, то вона ініціалізується при запуску, а її область видимості співпадає з областю дії і поширюється від точки об`яви до кінця файлу, якщо ж статична змінна об`явлена в середині, то вона ініціалізується лише при першому вході у відповідну функцію або блок. Значення зберігаються від одного виклику ф-ції до іншого. Таким чином статичні змінні можна використовувати для збереження значення змінних на протязі роботи програми. Статичні змінні не можуть бути об`явлені в інших файлах, як зовнішні. Якщо статична змінна не ініціалізується, то їй присвоюється значення 0.

Змінні класу volatile. В тих випадках коли необхідно передбачити можливість модифікації змінної периферійним пристроєм або іншою програмою використовується тип volatile. У зв`язку з цим компілятор не намагається оптимізувати програму шляхом розміщення змінної в регістрах.

...

Volatile short sTest

...

або

...

Volatile cons tint sTest

В другому випадку константа не може змінюватись в програмі, але може модифікуватися в залежності від зовнішніх факторів.

5. Простір імен

Визначення ф-цій і змінних у файлах заголовків пов’язано з поняттям простору імен. До введення цього поняття всі обявлення ідентифікаторів і констант в заготовочному файлі розміщалися компілятором в глобальний простір імен, що приводить до великої кількості конфліктів, пов’язаних з використанням різними об’єктами однакових імен в одній програмі. Коли в програму включається заголовок нового стилю, його вміст розміщається не в глобальний простір а в простір std. Якщо в програмі треба визначити деякі ідентифікатори, які, як ви підозрюєте. Можуть перевизначати вже існуючі, просто треба завести свій власний новий простір імен. Для цього використовується ідентифікатор namespace.

namespaceімя простору імен

{

//обяви

}

Таким чином після цього обяви в середині простору імен будуть знаходитись тільки в його області видимості.

namespaceNewNameSpace

{

intx,y,z;

voidsome_function(char smb);

}

Int main ()

{

NewNameSpace::x=5;

return 0;

}

Якщо :: використовуються часто, то можна використати інструкціюusing , яка має дві форми:

1) using namespace імя_простору ;

2)usingшмя_простору::ідентифікатор;

1)В першому випадку компілятору повідомляється, що в подальшому необхідно використовувати ідентифікатори з вказаного простору, поки не зустрінеться інша інструкція using.

using Namespace;

x=0;

y=z=4;

some_function(‘A’);

На практиці часто явно вказується явне позначення області: usingnamespacestd;

2) Друга форма дозволяє компілятору використовувати вказаний простір лише для конкретного ідентифікатора.

using namespace std;

using NEwNameSpace::z;

так можна використовувати ідентифікатори стандартної бібліотеки с і цілочислову змінну z.

6. Вбудовані (inline-) функції.

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

inlineint sum(int, int)

Int main()

{

int a=2;

int b= 6;

int c=3;

cout<<sum(a, b);

cout<<sum(b, c);

return 0;

}

int sum(int x, int y)

{

returnx+y;

}

8. Стек і функції (обробка рекурсивних викликів).

Стек – спеціальна область пам’яті, що виділена для збереження даних програми, що потрібні кожній функції, яка викликається. Стек діє по принципу «останній прийшов, перший вийшов» (останній елемент доданий у функцію виводиться першим), структура типу LIFO (Lost in, first out).

При розміщенні даних в стек, він розширюється, а при поверненні даних з стек – він звужується.

Вершина стеку – вільне місце в стеку, на яке вказує спеціальний регістр – показник вершини стеку. При розміщенні (видаленні) елемента в стек (з нього) змінюється лише значення показника вершини стека.

Типові дії, що виникають при обробці виклику функції:

  1. Збільшується адреса, що міститься в показнику команди, щоб вказати на інструкцію, що знаходиться після виклику функції. Потім ця адреса поміщається в стек і буде служити адресою повернення повернення по завершенню виконання функції.

  2. У стеку резервується лише місце для значення, що повертається функції, якщо в системі з двохбайтовими цілими для значення, що повертається об’являється значення int (але в них нічого не заноситься)

  3. В показник команди загружається адреса викликаної функції, що зберігається в окремій відведеній для цього області пам’яті. Тому наступна виконувана команда – перший оператор виконуваної функції.

  4. Поточна вершина стека відмічається і міститься в його показнику. Все, що добавляється в стек з цього моменту і до тих пір поки функція не завершиться, розглядається як локальні дані цієї функції.

  5. В стек поміщаються всі аргументи, що передаються функції.

  6. Виконується команда, адреса якої знаходиться в показнику команди в даний момент, тобто перший рядок коду функції.

  7. По мірі визначення в стеку розміщуються локальні змінні і функції

  8. Коли ф-ція завершується, значення, що поверталися, розміщуються в області стека зарезервованій на 2 місці. Потім з стека видаляється весь вміст (разом з показником) стек очищається від локальних змінних і аргументів. Тоді з стека дістають значення поверненої функції, що присвоюється змінній, яка викликає цю функцію і адреса команди. Що над показником команди.

7. Поняття рекурсивних функцій.

Функція може викликати сама себе - це називається рекурсією. Рекурсія може бути прямою і непрямою.

Коли функція викликає сама себе, то це пряма рекурсія, якщо функція викликає іншу функцію, яка потім викликає першу, то це непряма .

Коли функція викликає сама себе, то виконується нова копія цієї функції, при цьому локальні змінні у 2 версії незалежні від локальних змінних першої версії і не можуть безпосередньо взаємно впливати одна на одну.

Прикладом рекурсивної функції є обчислення чисел Фібоначчі: кожен наступний член починаючи з 3 дорівнює сумі двох попередніх.

Для рекурсивних функцій важливою є умова зупинки рекурсій, наче, вона ніколи не закінчується. Для чисел Фібоначчі f>=3.

Алгоритм обчислення чисел Фібоначчі :

  1. Вказуємо число n.

  2. Виклик ф-ції Фібоначчі здійснюється використанням аргумента, якщо n<3, то ф-ція fib () викликає саму себе (рекурсивно), передаючи в якості аргументу значення n-1, а після цього повертає значення їх суми.

// Рекурсія чисел Фібоначчі

# include <iostream.h>

Int fib (int n);

Int main ()

{ int n, answer;

cout <<”Enter number to find:”;

cin >> n;

cout <<”\n\n”;

answer = fib(n);

cout <<answer<<”is the”<<n<<”the Fibonachi number\n”;

return 0;

}

Int fib(int n)

{

cout <<”Processing fib(“<<n<<”)….”;

If (n<3)

{

cout <<”return 1\n”;

return (1);

}

else

{

cout<<”call fib(”<<n-2<<”) and fib(“<<n-1<<”)\n”;

return (fib n-2)+fib(n-1);

}

}

9. Математичні функції

math.h - заголовний файл стандартної бібліотеки мови програмування С, розроблений для виконання простих математичних операцій. Більшість функцій залучає використання чисел з плаваючою крапкою.. C++ також реалізовую дані функції для забезпечення сумісності, усі вони містяться у заголовному файлі cmath

Всі ці функції приймають double, якщо не визначено інакше. Для роботи з типами float і long double використовуються функції з постфіксами f і l відповідно. Всі функції, що приймають або повертають кут, працюють з радіанах.

Функції

Ім'я Опис

acos арккосинус

asin арксинус

atan арктангенс

atan2 арктангенс з двома параметрами

ceil округлення до найближчого більшого цілого числа

cos косинус

cosh гіперболічний косинус

exp експоненційна функція

fabs абсолютне значення

floor округлення до найближчого меншого цілого цілого

fmod повертає залишок від ділення двох чисел

frexp повертає значення мантиси і експоненти

ldexp вираховує значення x*2exp

log натуральний логарифм

log10 десятковий логарифм

modf(x,p) повертає цілу та дробову частину аргументу х зі знаком

pow(x,y) вираховує значення xy

sin синус

sinh гіперболічний синус sqrt квадратний корінь tan тангенс tanh гіперболічний тангенс

ст. 17-18

11. Поняття показника.

Місцезнаходження будь-якого об єкта в памяті визначається його адресою, розмір зарезервованого місця в памяті залежить від типу змінної, а для доступу до вмісту об’єкта служать його імя,(слово індифікатор ) для того щоб визначити адресу конкретної змінної служить унарна операція взяття адреси( амперсанд перед імям змінної ). Результат адреса задається в стандартному типі.

Могутній засіб мови С++ - безпосередній доступ до памяті, для чого застосовується спеціальний тип змінних показник(Pointer) - представляє собою змінну, значення якої є адреса комірки памяті,ця змінна вказує на початок області оперативної памяті,де знаходиться об’єкт. Показник може посилатись на змінну , базового або похідного типу у роботі масивів/класів .

Обява показника (синтаксис) має вигляд :

тип_об’єкта*індифікатор

Показник завжди займає 2або 4 байта в залежності від моделі памяті. Схематично показник зоображається:

12 Операція непрямого звернення до показників, розіменування.Для доступу до об'єкту через вказівник використовується оператор розіменування *, що здійснює так званунепряму адресацію: *p означає «об'єкт, на який вказує p». По суті *p є ссилкою на об'єкт.

Спроба розіменування нульового вказівника приводить до помилки при виконанні програми, спроба ж розіменуваннявказівника void*(див. розділ 2.4) викличе помилку на етапі компіляції.

Однією з поширених помилок є розіменування неініціалізованих вказівників. Наприклад, в будь-якому з наступних випадків результат роботи програми непередбачуваний:

char* s;

*s=’a’; // помилка!

cin>>s; // помилка!

17. Показник може посилатися на інший показник. Це добувається відповідним заданням числа * при об`яві, що вказує на порядок і щоб отримати це значення такий показник повинен бути розіменованим відповідне число раз:

...

int **pptrInt;

...

char ***ppSymbol (показник на показник,який сам є показником)

...

-----

...

charmychar;

char *pSymbol=&mychar;

char **pptr=&pSymbol;

char ***ppptr=&pptr;

...

***ppptr=7;

...