Модуль 1 Основи алгоритмізації та елементи мови програмування. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Модуль 1 Основи алгоритмізації та елементи мови програмування.



Абетка мови.

Ідентифікатори. Опис змінних.

Операції.

Структура простої програми.

1. Абетка мови.

1. Букви A-Z, a-z (прописні й рядкові).

2. цифри 0-9.

3. спец. Смволи.: _${}()[].-=*/%<>=!&',:;?|~”\

 

2. Ідентифікатори. Опис змінних.

  У мові С всі використовувані змінні повинні бути описані. Звичайно це робиться на початку функції (про8грама називається функцією) до першого виконуваного оператора.

Після описів - виконувана частина програми. Весь текст програми у фігурних дужках {...}. Ці дужки використаються й для складання операторів.

 

Операції.

Основні операції мови З++

Унарні

++                           збільшення на 1

--                                  зменшення на 1

sizeof                        розмір

-                                     порозрядне заперечення

!                                     логічне заперечення

&                                   узяття адреси

new                         виділення пам'яті

delete                        звільнення пам'яті

type                    перетворення типів

Бінарні

*                           множення

/                        розподіл

 %                           залишок від розподілу

+                          додавання

-                           вирахування

<<                                  зрушення вліво

>>                                  зрушення вправо

<                          менше

<=                                  менше або більше

>                          більше

>=                           більше або дорівнює

= =                       дорівнює

!=                         нерівно

&                         порозрядна Кон'юнкція (И)

|                       порозрядна Диз'юнкція (АБО)

&&                логічне (И)

||                           логічне (АБО)

?:                         умовна операція

=                        присвоювання

*=                                  множення із присвоюванням

/=                         розподіл із присвоюванням

 %=                     залишок від розподілу із присвоюванням

+=                                  додавання із присвоюванням

-=                        вирахування із присвоюванням

 

Структура простої програми.

Програма мовою З++ складається з функцій, описів і директив препроцесора (с.16). Одна з функцій повинна мати ім'я Main. Виконання програми починається з першого оператора цієї функції. Найпростіше визначення функції має наступний формат:

Тип_ щоповертає_значення ім'я ([параметри]) {

оператори, що становлять тіло функції

}

Як правило, функція використається для обчислення якого-небудь значення, тому перед ім'ям функції вказується його тип. Про функції розповідається на с.73, нижче наведені лише самі необхідні відомості:

q Якщо функція не повинна повертати значення, указується тип Void;

q Тіло функції є блоком й, отже, полягає у фігурні дужки;

q Функції не можуть бути вкладеними;

Кожен оператор закінчується крапкою з коми (крім складеного оператора).

Приклад структури програми, що містить функції Main, F1 й F2:

 

директиви препроцесора

опису

Int main () {

оператори головної функції

}

int f1 () {

оператори функції F1

}

int F2 () {

оператори функції F2

}

Програма може складатися з декількох модулів (вихідних файлів). Кілька попередніх зауважень про введення/виводі. У мові З++ немає убудованих засобів введення/виводу - він здійснюється за допомогою функцій, типів й об'єктів, що втримуються в стандартних бібліотеках. Використається два способи:

функції, успадковані з мови З, і об'єкти З++.

Основні функції введення/виводу в стилі З:

Int scanf (const char* format, …) // введення

Int printf (const char* format, …) // вивід

Вони виконують форматованне введення й вивід довільної кількості величин у відповідності з рядком формату Format. Рядок формату містить символи, які при виводі копіюються в потік (на екран) або запитується з потоку (із клавіатрури) при введенні, і специфікації перетворення, що починаються зі знака %, які при введенні й виводі заміняються конкретними величинами. Список найбільш уживаних специфікацій перетворення наведений у додатку 2. Приклад програми, що використає функції введення/виводу в стилі З:

#include <stdio.h>

int main () {

int i;

printf (“Уведіть ціле число \n”);

scanf (“%d”, &i);

printf (“Ви ввели число %d, спасибі! ”, i);

return 0;

}

Перший рядок цієї програми - директива препроцесора, по якій у текст програми уставляється заголовний файл <stdio.h>, що містить опис використаних у програмі функцій введення/виводу (у цьому випадку кутові дужки є елементом мови). Всі директиви препроцесора починаються зі знака #. Третій рядок - опис змінної цілого типу з ім'ям i. Функція printf у четвертому рядку виводить запрошення «Уведіть ціле число» і переходить на новий рядок відповідно до керуючої послідовності \n. Функція scanf заносить введене із клавіатури ціле число в змінну i (знак & означає операцію одержання адреси), а наступний оператор виводить на екран зазначену в ньому рядок, замінивши специфікацію перетворення на значення цього числа.

А от як виглядає та ж програма з використанням бібліотеки класів З++:

#include<iostream.h>

int main () {

int i;

cout<< “Уведіть ціле число \n”;

cin >>i;

cout<< “Ви ввели число” <<i << “, Спасибі! ”;

return 0;

}

Заголовний файл <iostream.h> містить опис набору класів для керування введенням/виводом. У ньому визначені стандартні об'єкти - потоки cin для введення із клавіатури й cout для виводу на екран, а також операції приміщення в потік << і читання з потоку >>.

 

Структуру програми можна простежити, проаналізувавши наступну програму, що друкує таблицю температур по Фаренгейту і їхнім еквівалентам по 100-градусній шкалі Цельсія (по формулі з=(5/9)*(F-32))

Виведена програмою таблиця

Програма:

/* печатка Фаренгейт-Цельсій

таблиці F=0, 20,..., 300*/                     коментар

main()

{

int nash, kon, shcag;

float far, cel;

nash=0;

while(far<=kon){

           cel=(5.0/9.0)*(far-32.0);

           printf(“%4.0f %6.1f\n”, far, cel);

           far=far+shcag;

           }

}

  Програма на С складається з однієї або більше функцій. Одна із цих функцій повинна мати ім'я main. Від інших ця функція відрізняється тим, що її не можна викликати із себе, а її параметри якщо вони є, задаються операційною системою. MAIN звичайно складається першої в тексті програми, але це не обов'язково інші функції нічого не роблять:

  USELLET()

{

}

У прикладі це основна програма, що складається з однієї функції, її ім'я MAIN.

___________________________________________________________________

 

Константи.

Коментарі.

Константи.

1. Цілі. Вони підрозділяються на:

    а) десяткові: 0-9

    б) восьмеричні: 012-128

    в) шістнадцятирічні 0х12-1216

2. Довгі цілі визначаються явно латинською буквою l або L, що коштує після константи.

3. Константи із плаваючою крапкою. Завжди мають крапку константи із плаваючою крапкою складається з:

    цілої частини - наступна цифра.

    Десяткової крапки

    Дробової крапки - наступних цифр

    Символу експоненти е або Е

Експоненти у вигляді цілої const (м.б. зі знаком).

Кожна з наступних частин м.б. операндом:

1. цілої або дробової частини

2. десяткова крапка або символ Е.

Має тип double завжди.

    4. Символьні константи. Вона складається з одного символу ув'язненого в апострофи, виділяють спеціальні (керуючі символи) константи:

    переклад рядка                    HL (LF) ‘\N’

горизонтальна табуляція          HT         ‘\T’

вертикальна табуляція                  VT         ‘\V’

повернення на крок                   BS         ‘\B’

повернення каретки                   CR         ‘\R’

переклад формату                     FF         ‘\F’

зворотна коса                  \             ‘\\’

апостроф                          ‘             ‘\’’

лапки                                “            ‘\”’

порожній символ                       NUL      ‘\0’

Має тип int у вигляді символьної константи.

Крім цього символ м.б. представлений послідовністю 3-х восьмеричних цифр у вигляді:

    Пробіл - це '\040';

    Смвол ';' - це '\073'

Смвол 'a' - це '\141'

Смвол - це '\176'

    5. Строкові константи. Послідовність символів, укладених у лапки (не апострофи) є символьною константою.

    “Це строкова константа”

    “А” “132-321?” “0”

    Строкові константи - це масив символів. Має тип char[] завжди

 

Коментарі.

Коментар починається парою символів /* і закінчуються */.

Коментар дозволяється скрізь, де припустимі пробіли, переклади на новий рядок і переклад сторінки використаються як роздільники. Замість одного з них можна використати їхню кількість.

Для підвищення читаності програми рекомендується використати символ табуляції.

Застосування коментарів.

1) /* це однорядковий коментар*/

2) /* це

   багаторядковий

 комен-

тар                           

 /*

    Коментарі не вкладаються друг у друга.

___________________________________________________________________


 

Типи даних – основні типи.

Операції, їх знаки, вирази.

Операції, їх знаки, вирази.

 

Вираз складаються з операндів, знаків операцій і дужок і використаються для обчислення деякого значення певного типу. Кожен операнд є, у свою чергу, виразм або одним з його окремих випадків - константою або змінної. Приклади виражень:

(a+0.12) /6

x && y ||!z

(t * sin(x)-1.05e4)/((2 * k + 2) * (2 * k + 3))

Операції виконуються відповідно до пріоритетів. Для зміни порядку виконання операцій використаються круглі дужки. Якщо в одному вираженні записано кілька операцій однакового пріоритету, унарні операції, умовна операція й операції присвоювання виконуються праворуч ліворуч, інші – ліворуч праворуч. Наприклад, a = b = c означає a = (b = c), а a + b + c означає (a + b)+c. Порядок обчислення підвиразів усередині виражень не визначений: наприклад, не можна вважати, що у вираженні (sin (x + 2) + cos (y +1)) звертання до синуса буде виконана раніше, ніж до косинуса, і що x+2 буде обчислено раніше, ніж y+1. Результат обчислення вираз характеризується значенням і типом. Наприклад, якщо a й b - змінні цілого типу й описані так:

Int a = 2, b = 5;

те вираз а + b має значення 7 і тип int, а вираз a = b має значення, рівне поміщеному в змінну a (у цьому випадку 5) і тип, що збігається з типом цієї змінної. Таким чином, у З++ припустимі вираз виду a = b = c: спочатку обчислюється вираз b = c, а за тим його результат стає правим операндом для операцій присвоювання змінної а. У вираз можуть входити операнди різних типів. Якщо операнди мають однаковий тип, то результат операції буде мати той же тип. Якщо операнди різного типу, перед обчисленнями виконуються перетворення типів за певними правилами, що забезпечує перетворення більше коротких типів у більше довгі для збереження значимості й точності.

Оператор вибору switch.

Оператор вибору switch.

Оператор switch (перемикач) призначений для розгалуження процесу обчислень на кілька напрямків. Формат оператора:

switch (вираз){

case константний_вираз_1: [список_операторів_1]

case константний_вираз_2:  [список_операторів_2]

сase константний_вираз_n: [список_операторів_n] [default: оператори ]

}

 

     
 


Операторы
Операторы n
Операторы 2

                                    

                          default

 

 


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

Вихід з перемикача звичайно виконується за допомогою операторів break або return. Оператор break виконує вихід із самого внутрішнього з об’емлющих його операторів switch, for, while й do. Оператор return виконує вихід з функції, у тілі якої він записаний.

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

Приклад (програма реалізує найпростіший калькулятор на 4 дії):

#include <iostream.h> int main(){

int a, b, res;

char op;

cout << “\n Уведіть 1й операнд: “; cin >> a;

cout << “\n Уведіть знак операції: “; cin >> op:

cout << “\n Уведіть 2й операнд: “; cin >> b;

bool f = true;

switch (op){

case ' + ': res = a + b; break;

case '-': res = a - b; break;

case '*': res = a * b; break;

case '/': res = a / b; break:

default: cout <<” \n Невідома операція”; f = false;

}

if (f) cout << “ \n Результат: “ << res;

return 0;

}

ПРИМІТКА

У випадку синтаксичної помилки в слові default повідомлення про помилку не видається, оскільки компілятор сприйме це слово як припустиму мітку оператора.

Приклад (програма реалізує найпростіший калькулятор на 4 дії):

#include <iostream.h>

int main(){

int a, b, res;

char op;

cout << “\n Уведіть 1й операнд: “; cin >> a;

cout << “\n Уведіть знак операції: “; cin >> op:

cout << “\n Уведіть 2й операнд: “; cin >> b;

bool f = true;

switch (op){

case ' + ': res = a + b; break;

case '-': res = a - b; break;

case '*': res = a * b; break;

case '/': res = a / b; break:

default: cout <<” \n Невідома операція”; f = false;

}

if (f) cout << “ \n Результат: “ << res;

return 0;

}

Оператор goto

Оператор безумовного переходу goto має формат:

goto мітка; У тілі тієї ж функції повинна бути присутнім рівно одна конструкція виду:

мітка: оператор;

Оператор goto передає керування на позначений оператор. Мітка — це звичайний ідентифікатор, областю видимості якого є функція, у тілі якої він заданий.

Застосування goto порушує принципи структурного й модульного програмування, по яких всі блоки, з яких складається програма, повинні мати тільки один вхід й один вихід.

У кожному разі не слід передавати керування усередину операторів if, switch і циклів. Не можна переходити усередину блоків, що містять ініціалізацію змінних, на оператори, розташовані після її, оскільки в цьому випадку ініціалізація не буде виконана:

int k;...

goto metka;...

{int a = 3, b = 4;

 k = a + b;

metka: int m = k + 1;...

}

Після виконання цього фрагмента програми значення змінної m не визначене.

Оператор break

Оператор break використається усередині операторів циклу або switch для забезпечення переходу в крапку програми, що перебуває безпосередньо за оператором, усередині якого перебуває break.

Приклад. Програма обчислює значення гіперболічного синуса речовинного аргументу х із заданою точністю eps за допомогою розкладання в нескінченний ряд.

sh х = 1 + х3/3! + х5/5! + х7/7! +...

Обчислення закінчується, коли абсолютна величина чергового члена ряду, що додає до суми, стане менше заданої точності.

#include<iostream.h>

#include<math.h>

int main () {

const int MaxIter = 500;                 //обмежник кількості ітерацій

double x, eps;

cout<<”\n Уведіть аргумент і точність: ”;

cin>> x >> eps;

bool flag = true;                              //ознака успішного обчислення

double y = x, ch = x;                      //сума й перший член ряду

for (int n = 0; fabs(ch) > eps; n++) {

ch *= x * x / (2 * n + 2)/(2 * n + 3); //черговий член ряду

y += ch;

if (n>MaxIter) {

           cout<<”/n Ряд розходиться!”;

           flag = false; break; }

}

if (flag) cout<<”/n Значення функції: ”<<y;

return 0;

}

Оператор continue

Оператор переходу до наступної ітерації циклу continue пропускає всі оператори, що залишилися до кінця тіла циклу, і передає керування на початок наступної ітерації.

Оператор return

Оператор повернення з функції return завершує виконання функції й передає керування в крапку її виклику. Вид оператора:

return [ вираз ];

Вираз повинне мати скалярний тип. Якщо тип значення, що повертає функцією, описаний як void, вираз повинен бути  відсутнім.

___________________________________________________________________

 

Типи циклів.

Оператор for.

1. Типи циклів.

Для зручності, а не по необхідності, в C++ є три різних оператори циклу -

while, do while й for.

Оператори циклу використаються для організації багаторазово повторюваних обчислень. Любою цикл складається з тіла циклу, тобто тих операторів, які виконуються кілька разів, початкових установок, модифікації параметра циклу й перевірки умови продовження виконання циклу.

2. Оператор for.

Оператор for переважніше для організації циклів з лічильниками.

Цикл із параметром має наступний формат:

for (ініціалізація; вираз; модифікації) оператор;

Ініціалізація використається для оголошення й присвоєння початкових значень величинам, використовуваним у циклі. У цій частині можна записати трохи операторів, розділених комі (операцією «послідовне виконання»), наприклад, так:

for (int i = 0, j = 2;...

int k, m;

for (k = 1, m = 0;...

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

Вираз визначає умова виконання циклу: якщо його результат, наведена до типу bool, дорівнює true, цикл виконується. Цикл із параметром реалізований як цикл із передумовою.

Модифікації виконуються після кожної ітерації циклу й служать звичайно для зміни параметрів циклу. У частині модифікацій можна записати трохи операторів через кому. Простий або складовій оператор являє собою тіло циклу. Кожна із частин оператора for може бути опущена (але крапки з коми треба залишити на своїх місцях!).

Приклад (оператор, що обчислює суму чисел від 1 до 100):

for (Int i = 1, s = 0; 1<=100; i++) s += i;

Приклад (програма друкує таблицю значень функції в=х2+1 в введеному діапазоні):

#Include <stdio.h>  

Int main(){

float Xn, Xk, Dx, X;

printf (“Уведіть діапазон і крок зміни аргументу: ");

scanf (“%f%f%f”, &Xn, &Xk, &Dx);

printf (“| X | Y |\n");

for (X = Xn; X<=Xk; X+=Dx)

printf (" | %5.2f | %5.2f |\n”, X*X + 1);

return 0;

}

Приклад (програма знаходить всі дільники цілого позитивного числа):

#Include <iostream.h> Int main(){

Int num, half, div;

cout << “\n Уведіть число: "; cin >> num;

for (half = num / 2, div = 2; div <= half; div++)

if (!(num %div))cout << div <<"\n";

return 0;

}

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

Любою цикл while може бути наведений до еквівалентному йому циклу for і навпаки за наступною схемою:

for (b1: b2; bз) оператор b1;

while (b2){ оператор; bз;}

 Часто, що зустрічаються помилки, при програмуванні циклів — використання в тілі циклу неініціалізованих змінних і невірний запис умови виходу із циклу.

Щоб уникнути помилок, рекомендується:

q перевірити, чи всім змінним, що зустрічається в правій частині операторів присвоювання в тілі циклу, привласнені до цього початкові значення (а також чи можливо виконання інших операторів);

q перевірити, чи змінюється в циклі хоча б одна змінна, вхідна в умову виходу із циклу;

q  передбачити аварійний вихід із циклу по досягненню деякої кількості ітерацій;

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

Оператори циклу взаємозамінні, але можна привести деякі рекомендації з вибору найкращого в кожному конкретному випадку.

___________________________________________________________________

 

Обробка масивів.

Одновимірні масиви

Масив утворюється рядом елементів одного типу. Для вказівки компілятору про необхідність обробки даних у вигляді масиву використовуються оголошення. При оголошенні масиву компілятор повідомляється про кількість і тип елементів, що входять до складу масиву.

Оголошення масиву

Синтаксис:

<специфікація типу><декларатор> {<консm. вираз>]; <специфікація типу><декларатор> [];

Тут квадратні дужки - це термінальні символи. Оголошення масиву визначає тип масиву і тип кожного елемента. Воно може визначати також число елементів в масиві. Змінна типу масив розглядається як покажчик на елементи масиву. Оголошення масиву може представлятися в двох синтаксичних формах, вказаних вище. <Декларатор> задає ім'я змінної. Квадратні дужки, наступні за декларатором, модифікують декларатор на тип масиву. <Константний вираз>, укладений в квадратні дужки, визначає число елементів в масиві. Кожний елемент має тип, що задається <специфікатором типа>, який може специфікувати будь-який тип, виключаючи void і тип функції.

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

Наприклад:

Int days[] = {31, 28, 31, ЗО, 31, 31};

При використанні порожніх квадратних дужок для ініціалізації масиву компілятор підраховує кількість елементів в списку і встановлює розмір масиву рівним цьому числу.

Типу масив відповідає пам'ять, яка потрібна для розміщення всіх його елементів. Елементи масиву з першого до останнього запам'ятовуються в послідовних зростаючих адресах пам'яті. Між елементами масиву в пам'яті розриви відсутні. Елементи масиву запам'ятовуються один за одним послідовно, а доступ до них здійснюється за допомогою цілочисельного індексу (або шляхом вказівки зсуву).

Наприклад:

int scores[10], game;

char *name[20];

В першому прикладі оголошується змінна типу масив з ім'ям scores з 10 елементів типу int. Змінна з ім'ям game оголошена як проста змінна цілого типу.

В другому прикладі оголошений масив покажчиків. Масив складається з 20-ти елементів, кожний з яких є покажчиком на величину типу char.

В мові Сі перший елемент має індекс 0, тому останній елемент масиву має індекс, рівний n - 1.

Значення елементам масиву можна привласнювати, використовуючи індекс масиву, або порядковий номер.

___________________________________________________________________

 

 

Оператори while, do while.

1. Оператори while, do while.

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

Змінні, що змінюються в тілі циклу й використані при перевірці умови продовження, називаються параметрами циклу. Цілі параметри циклу, що змінюються з постійним кроком на кожній ітерації, називаються лічильниками циклу.

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

Цикл завершується, якщо умова його продовження не виконується. Можливо примусове завершення як поточної ітерації, так і циклу в цілому. Для цього служать оператори break, continue, return й goto (див. тему «Оператори передачі керування»). Передавати керування ззовні усередину циклу не рекомендується.

 

 

Начальные установки  
Начальные установки  

                       а                                                                       б

          

               
 
 
 

 

 


Схеми операторів циклу: а - цикл із передумовою; б - цикл із післяумовою

Для зручності, а не по необхідності, в C++ є три різних оператори циклу -

while, do while й for.

Оператор do while звичайно використають, коли цикл потрібно обов'язково виконати хоча б раз (наприклад, якщо в циклі виконуються введення даних).

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

 

 

Вказівники.

Ініціалізація вказівників.

Масиви та вказівники.

Вказівники.

 

Коли компілятор обробляє оператор визначення змінної, наприклад, int i=10;, він виділяє пам'ять відповідно до типу (int) і ініціалізує її зазначеним значенням (10). Всі обіги в програмі до змінного по її імені (i) заміняються компілятором на адресу області пам'яті, у якій зберігається значення змінної. Програміст може визначити власні змінні для зберігання адрес областей пам'яті. Такі змінні називаються покажчиками.

Отже, покажчики призначені для зберігання адрес областей пам'яті. У З++ розрізняють три види покажчиків - покажчики на об'єкт, на функцію й на void, що відрізняються властивостями й набором припустимих операцій. Покажчик не є самостійним типом, він завжди пов'язаний з яким-небудь іншим конкретним типом.

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

тип (*ім'я) (список_типів_аргументів):

Наприклад, оголошення:

    int (*fun) (double, double);

задає покажчик з ім'ям fun на функцію, що повертає значення типу int і має два аргументи типу double.

Покажчик на об'єкт містить адреса області пам'яті, у якій зберігаються дані певного типу (основного або складеного). Найпростіше оголошення покажчика на об'єкт (надалі називаного просто покажчиком) має вигляд:

   тип *ім'я;

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

Зірочка ставиться безпосередньо до імені, тому для того, щоб оголосити кілька покажчиків, потрібно ставити її перед ім'ям кожного з них. Наприклад, в операторі

    int *a, b, *c;

описуються два покажчики на ціле з іменами a й c, а також ціла змінна b. Розмір покажчика залежить від моделі пам'яті. Можна визначити покажчик на покажчик і т.д.

Покажчик на void застосовується в тих випадках, коли конкретний тип об'єкта, адреса якого потрібно зберігати, не визначений (наприклад, якщо в одній і тієї ж змінній у різні моменти часу потрібно зберігати адреси об'єктів різних типів).

Покажчику на void можна привласнити значення покажчика будь-якого типу, а також порівнювати його з іншими покажчиками, але перед виконанням яких-небудь дій з областю пам'яті, на яку він посилається, потрібно перетворити його до конкретного типу явно.

Покажчик може бути константою або змінної, а також указувати на константу або змінну. Розглянемо приклади:

    int i;                                //ціла змінна

    const int ci=1;                 //ціла константа

    int *pi;                            //покажчик на цілую змінну

    const int * pci;                // покажчик на цілу константу

    int * const cp=&i;           //покажчик-константа на цілую змінну

    const int * const cpc=&ci; //покажчик-константа на цілу константу

Як видно із прикладів, модифікатор const, що перебуває між ім'ям покажчика й зірочкою, ставиться до самого покажчика й забороняє його зміна, а const ліворуч від зірочки задає сталість значення, на яке він указує. Для ініціалізації покажчиків використана операція одержання адреси &.

Величини типу покажчик підкоряються загальним правилам визначення області дії, видимості й часу життя.

Ініціалізація вказівників.

 

Покажчики найчастіше використаються при роботі з динамічною пам'яттю, називаної деякими естетами купою (переклад з англійської мови слова heap). Це вільна пам'ять, у якій можна під час виконання програми виділяти місце відповідно до потреб. Доступ до виділених ділянок динамічної пам'яті, називаним динамічними змінними, виробляється тільки через покажчики. Час життя динамічних змінних - від крапки створення до кінця програми або до явного звільнення пам'яті. У З++ використається два способи роботи з динамічною пам'яттю. Перший використає сімейство функцій malloc і дістався в спадщину від З, другий використає операції new й delete.

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

Існують наступні способи ініціалізації покажчика:

1. Присвоювання покажчику адреси існуючого об'єкта:

· за допомогою операції одержання адреси:

int a=5;        //ціла змінна

int * p=&a; //у покажчик записується адреса а

int * p (&a); //тим же саме іншим способом

· за допомогою значення іншого ініціалізованого покажчика:

int * r=p;

· за допомогою іменами масиву або функції, які трактуються як адреса:

int b[10];                         //масив

int * t=b;                         //присвоювання адреси початку масиву

void f(int5 a){/*...*/}    //визначення функції

void (*pf)(int);               //покажчик на функцію

pf=f;                               //присвоювання адреси функції

2. Присвоювання покажчику адреси області пам'яті в явному виді:

Char * vp=(char )0 хВ8000000;

Тут 0хв000000 - шістнадцаятирічна константа, (char *) - операція приведення типу: константа перетвориться до типу «покажчик на char».

3. Присвоювання порожнього значення:

int * suxx=NULL;

int * rulez=0;

У першому рядку використається константа NULL, певна в деяких заголовних файлах С як покажчик, дорівнює нулю. Рекомендується використати просто 0, тому що це значення типу int буде правильно перетворено стандартними способами відповідно до контексту. Оскільки гарантується, що об'єктів з нульовою адресою ні, порожній покажчик можна використати для перевірки, посилається покажчик на конкретний чи об'єкт ні.

4. Виділення ділянки динамічної пам'яті й присвоювання її адреси покажчику:

· за допомогою операції new:

int * n=new int;                               //1

int * m=new int (10);                      //2

int * q=new int [10];                       //3

· c допомогою функції malloc:

int * u=(int *)malloc(sizeof(int));  //4

В операторі 1 операція new виконує виділення достатнього для розміщення величини типу int ділянки динамічної пам'яті й записує адресу початку цієї ділянки в змінну n. Пам'ять під саму змінну n (розміру, достатнього для розміщення покажчика) виділяється на етапі компіляції.

В операторі 2, крім описаних вище дій, виробляється ініціалізація виділеної динамічної пам'яті значенням 10.

В операторі 3 операція new виконує виділення пам'яті під 10 величин типу int (масиву з 10 елементів) і записує адресу початку цієї ділянки в змінну q, що може трактуватися як ім'я масиву. Через ім'я можна звертатися до будь-якого елемента масиву.

Якщо пам'ять виділити не вдалося, по стандарті повинне породжуватися виключення bad_alloc. Старі версії компіляторів можуть повертати 0.

В операторі 4 робиться те ж саме, що й в операторі 1, але за допомогою функції виділення пам'яті malloc, успадкованої з бібліотеки С. У функцію передається один параметр - кількість виділюваної пам'яті в байтах. Конструкція (int) використається для приведення типу покажчика, що повертає функцією, до необхідного типу. Якщо пам'ять виділити не вдалося, функція повертає 0.

Операцію new використати переважніше, ніж функцію malloc, особливо при роботі з об'єктами.

Звільнення пам'яті, виділеної за допомогою операції new, повинне виконуватися за допомогою delete, а пам'яті, виділеною функцією malloc - за допомогою функції free. При цьому змінн-покажчик зберігається й може ініціалізується повторно. Наведені вище динамічні змінні знищуються в такий спосіб:

   delete n; delete m; delete [] q; free (u);

Якщо пам'ять виділялася за допомогою new [], для звільнення пам'яті необхідно застосовувати delete []. Розмірність масиву при цьому не вказується. Якщо квадратних дужок ні, то ніякого повідомлення про помилку не видається, але позначений як вільний буде тільки перший елемент масиву, а інші виявляться недоступні для подальших операцій. Такі комірки пам'яті називаються сміттям.

Увага!

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



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 43; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.117.81.240 (0.24 с.)