Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Всі відповіді СП.docx
Скачиваний:
10
Добавлен:
28.01.2023
Размер:
217.28 Кб
Скачать
  1. Системне програмування

    1. Дати оцінку основним правилам автоматичного перетворення типів.

Неявна конвертація типу (або “автоматичне приведення типу”) виконується всякий раз, коли потрібен один фундаментальний тип даних, але надається інший, і користувач не вказує компілятору, як виконати конвертацію (не використовує явну конвертацію типів через оператори конвертації).

Є 2 основних способи неявної конвертації типів даних:

  • числове розширення;

  • числова конверсія.

Числове розширення

Коли значення з одного типу даних конвертується в інший тип даних, який є більшим (за розміром і по діапазону значень), то це називається числовим розширенням. Наприклад, тип int може бути розширений в тип long, а тип float може бути розширений в тип double:

long l(65); // розширюємо значення типу int (65) в тип long

double d(0.11f); // розширюємо значення типу float (0.11) в тип double

В мові C++ є 2 типи розширень:

Інтегральне розширення (або “цілочисельне розширення”). Включає в себе конвертацію цілочисельних типів, менших, ніж int (bool, char, unsigned char, signed char, unsigned short, signed short) в int (якщо це можливо) або в unsigned int.

Конвертація з типу float в тип double.

Інтегральне розширення і розширення типу з плаваючою крапкою використовуються для перетворення “менших за розміром” типів даних в типи int/unsigned int чи double (вони найбільш ефективні для виконання різних операцій).

Числові конверсії

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

double d = 4; // конвертуємо 4 (тип int) в double

short s = 3; // конвертуємо 3 (тип int) в short

На відміну від розширень, які завжди є безпечними, конверсії можуть (але не завжди) призвести до втрати даних. Тому в будь-якій програмі, де виконується неявна числова конверсія, компілятор видаватиме попередження.

Є багато правил щодо виконання числової конверсії, але ми розглянемо тільки основні.

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

Обробка арифметичних виразів

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

Якщо операндом є ціле число, яке менше (за розміром/по діапазону) типу int, то воно піддається інтегральному розширенню в тип int або в unsigned int.

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

Пріоритет типів операндів:

  • long double (найвищий);

  • double;

  • float;

  • unsigned long long;

  • long long;

  • unsigned long;

  • long;

  • unsigned int;

  • int (найнижчий).

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

    1. Проаналізувати роботу з масивами вказівників і багатовимірними масивами в мові С++.

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

int* a[10];

Пртрбно памятати, що вказівники лише вказують на область виділеної памяті, тому щоб записати значення у вказівник, початку потрібно виділити пам'ять або сатичну, або динамічну. Також доступ до елементів масиву вказівників можливий через вказівник на перший елемент або за допомогою оператора [].

Приклад заповнення масу двома способами:

for (int i = 0; i < 10; i++)

{

a[i] = new int;

**(a + i) = i;

//*a[i] = i;

cout << "*a[i] = " << *a[i] << endl;

}

Багато вимірні масиви (2 і більшої розмірності) в С++ оголошуються наступним чином:

// масив цілих чисел розміром 3*5*6

int a[3][5][6];

а проінізіалузвати можна таким чином:

// ініціалізація масиву M цілих чисел розміром 2*3*4

int M[2][3][4] =

{

{

{ 8, 3, -5, 2 },

{ -3, 2, 8, 4 },

{ 1, 0, 3, -9 }

},

{

{ -2, 9, 5, 4 },

{ 1, 0, 2, 5 },

{ -8, 3, 4, 2 }

}

};

Доступ до елементів масиву також доступний через вказівник на перший елемент або за допомогою оператора []. Також потрібно розуміти, що багатовимірні масиви складаються із одновимірних, тому доступ до елементів через вказівник із збільшенням розрядності призводить до використання вказівників на вказівники, наприклад щоб вивести елемент масиву М[1][2][3] потрібно використати таку конструкцію

cout << "m[1][2][3] = " << *(*(*(M + 1) + 2) + 3) << endl;

А якщо використовувати оператор [] то вираз трохи спроститься:

cout << "m[1][2][3] = " << M[1][2][3] << endl;