
- •Конспект лекцій ( частина і ) з дисципліни
- •1. Поняття інформації та основні форми її подання
- •2. Представлення даних в пам’яті комп'ютера
- •3. Класифікація типів даних
- •4. Базові типи даних
- •4.1. Порожній тип
- •4.2. Логічний тип даних
- •4.3. Символьні типи даних
- •4.4. Цілочисельні типи даних
- •4.5. Дійсні типи даних
- •5. Похідні типи даних
- •5.1. Переліки
- •5.2. Вказівники
- •5.3. Посилання
- •5.4. Масиви
- •5.5. Структури
- •5.6. Бітові поля
- •5.7. Об'єднання
- •6. Перетворення типів
- •6.1. Неявне перетворення типів
- •6.1.1. Арифметичне перетворення типів
- •6.1.2. Перетворення типів при присвоюванні
- •6.2. Явне перетворення типів
- •6.3. Застаріла форма явного перетворення
- •Список літератури
- •1. Поняття інформації та основні форми її подання ------------------------------------------- 3
- •Основи представлення данних в пам'яті комп'ютера
- •6.050102 “Комп’ютерна інженерія
5.5. Структури
На відміну від масиву, всі елементи якого однотипні, структура може містити елементи різних типів. В мові C++ структура є видом класу і має всі його властивості, але в багатьох випадках доситатньо використовувати структури так, як вони визначені в мові С:
struct [ім'я_типу] {
тип_1 елемент _1:
тип_2 елемент _2;
тип_n елемент _n;
} [ список_оголошень ];
Елементи структури називаються полями структури і можуть мати будь-які типи, крім типу цієї ж структури, але можуть бути вказівниками на неї. Якщо відсутнє ім'я типу, то повинен бути заданий список оголошень перемінних, вказівників або масивів. В цьому випадку опис структури служить визначенням елементів цього списку, наприклад:
struct {
char fіo[30];
int date, code;
double salary;
} clerk, staff[100], *people; // визначення змінної типу структура, масиву
// структур і вказівника на структуру
Якщо список відсутній, опис структури визначає новий тип, ім'я якого можна використовувати надалі поряд зі стандартними типами, наприклад:
struct worker {
char fіo[30];
int date, code;
double salary;
}; // опис закінчується крапкою з комою
worker clerk, staff[100], *people; // інший спосіб визначення змінної типу струк-
// тура, масиву структур і вказівника на структуру
Ім'я структури можна використовувати відразу після його оголошення (визначення можна дати пізніше) в тих випадках, коли компіляторові не потрібно знати розмір структури, наприклад:
struct Lіst;. // оголошення структури Lіst
struct Lіnk{
Lіst *p; // вказівник на структуру Lіst
Lіnk *prev. *succ; // вказівник на структуру Lіnk
}:
struct Lіst { / * визначення структури Lіst * / };
Це дозволяє створювати зв'язані списки структур.
Для ініціалізації структури значення її елементів перелічують через кому у фігурних дужках у порядку їхнього опису:
struct{
char fio[30];
int date, code;
double salary;
}worker = {"Іваненко", 31, 215, 1400.55};
При ініціалізації масивів структур треба брати у фігурні дужки кожен елемент масиву:
struct complex{
float real, іm;
} compl [2][3] = {
{{1,1}, {1,1}, {1,1}}, // рядок 1, тобто цє масив compl[0]
{{2,2}, {2,2}, {2,2}} // рядок 2. тобто це масив compl[1]
};
Для змінних одного й того ж структурного типу визначена операція присвоювання, при цьому відбувається поелементне копіювання. Структуру можна передавати в функцію і повертати як значення функції.
Доступ до полів структури виконується за допомогою операцій вибору: "." (крапка) - при звертанні до поля через ім'я структури і "->" - при звертанні через вказівник, наприклад:
worker clerk, staff[100], *people;
. . .
clerk. fіo = "Іваненко";
staff[8].code = 215;
people ->salary = 1400.55;
Якщо елементом структури є інша структура, то доступ до її елементів виконується через дві операції вибору:
struct А {іnt а; double х;};
struct B {А а; double х;} х[2];
х[0].а.а = 1;
х[1].х = 0.1;
Як видно з прикладу, поля різних структур можуть мати однакові імена, оскільки в них різна область видимості. Більше того, можна оголошувати в одній області видимості структуру та інший об'єкт (наприклад, змінну або масив) з однаковими іменами.
В пам'яті комп’ютера під кожний елемент структури виділяється визначений відповідно до типу цього елемента об’єм памяті. Елементи в пам'яті зберігаються в тому ж порядку, в якому вони були представлені в описі структури.
Розмір змінної структурного типу не можна обчислити просто як суму його елементів, тому що змінні певних типів мають вирівнюватись в пам'яті комп’ютера по деяким залежним від реалізації границям, наприклад, повинні бути вирівняні по границі слова. Це може призводити до "дірок" в структурі. Значення в таких "дірках" невизначені. Навіть якщо значення двох змінних одного й того ж структурного типу дійсно рівні між собою, то не обов’язково, що при порівнянні вони виявляться рівними один одному, оскільки малоймовірно, що невизначені "дірки" містять однакові значення. Отже, порівняння структур є синтаксичною помилкою через різні вимоги по вирівнюванню в різних системах.
Приклад 10.
Розглянемо структуру:
struct ех{
double d;
char k[5];
struct koor { int x, y;} ab;
bool b;
char c;
} rec = {2,"my",{4,5},true,'9'};
Визначимо представлення в пам'яті комп’ютера окремо кожного поля:
1). Представлення дійсної змінної : double d = 2;
2 10 = 2,0 10 = 2,0 16 = 0010 , 0000 2
Нормалізація: 001, 0 0000 * 20001
Мантиса: m=0 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000
Зміщений порядок: е = 102310 + 110 = 1024 10 = 400 16 = 100 0000 0000 2
Знак: s=0
Зборка за схемою:
1біт |
11 біт |
52 біта |
s |
e |
m |
0 |
100 0000 0000 |
0 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000 |
В 16- ковій системі числення:
0
100 0000
0000
0 0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
000
2 =
4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16
В пам’яті комп’ютера буде зберігатися у зворотному порядку розміщення байт числа. Результат в 16- ковій системі числення: 00 00 00 00 00 00 00 40
2). Представлення символьного рядка : char k[5] = "my";
В пам’яті комп’ютера він зберігається в такому вигляді:
0110
1101
0111 1001
0000 0000
0000
0000
0000
0000
my[0] = 'm' my[1] = 'y' my[2] = '\0' my[3] = '\0' my[4] = '\0'
код символа: код символа: признак признак признак
10910 = 6D16 12110 = 7916 кінця рядка кінця рядка кінця рядка
Результат в 16- ковій системі числення: 6D 79 00 00 00
3). Представлення структури: struct koor { int x, y;} ab = {4,5};
Додатнє число 4 типу int
в пам'яті комп’ютера зберігається в
прямому двійковому коді і займає 4 байти:
410
= 416
= 01002
0000 0000 0000 0000 0000 0000 0000
0100
В пам’яті комп’ютера цілі числа зберігаються у зворотному порядку розміщення байт числа:
0000 0100 0000 0000 0000 0000 0000 0000
Результат в 16-ковій системі числення: 04 00 00 00.
Додатнє число 5 типу
int в пам'яті комп’ютера
зберігається в прямому двійковому коді
і займає 4 байти: 510
= 516
= 01012
0000 0000 0000 0000 0000 0000 0000
0101
В пам’яті комп’ютера цілі числа зберігаються у зворотному порядку розміщення байт числа:
0000 0101 0000 0000 0000 0000 0000 0000
Результат в 16-ковій системі числення: 05 00 00 00.
Отже, структура в пам’яті комп’ютера зберігається в такому вигляді: 04 00 00 00 05 00 00 00
4). Представлення логічної змінної : bool b = true;
В пам’яті комп’ютера змінна b зберігається як така послідовність біт: 0000 0001.
В 16-ковій системі числення: 01
5). Представлення символьної змінної : char c = ’9’;
За системою ASCIІ: символ ’9’ має порядковий номер 5710 = 3916 = 001110012
Отже, цей символ в пам’яті комп’ютера буде представлений як послідовність 0011 1001.
В 16-ковій системі числення: 39
Елементи в пам'яті зберігаються в тому ж порядку, в якому вони були представлені в описі структури: представлення дійсної змінної (sizeof(double) = 8 байт), далі представлення символьного рядка (sizeof(char k[5]) = 1 * 5 = 5 байт), далі представлення структури типу koor (sizeof(koor) = 4 * 2 = 8 байт), далі представлення логічної змінної (sizeof(bool) = 1 байт), далі представлення символьної змінної (sizeof(char) = 1 байт).
Сумування довжин всіх полів: 8 + 5 + 8 + 1 + 1 = 23 байта. Насправді, довжина структури sіzeof (ех) дорівнює 32 байта, а не 23 байта, як можна було б очікувати. Причина цього полягає в тому, що деякі поля певних типів вирівнюються в пам'яті комп’ютера по границі слова (або подвійного слова, або півслова):
вирівнювання вирівнювання по довжині
double d char k[5] по довжині слова struct koor bool char подвійного слова
00 00 00 00 00 00 00 40 6D 79 00 00 00 CC CC CC 04 00 00 00 05 00 00 00 01 39 CC CC CC CC CC CC
└ 1 слово ┘└ 2 слово ┘ └ 3 слово ┘└─ 4 слово ─┘└ 5 слово ┘└ 6 слово ┘└─ 7 слово ─┘└─ 8 слово ─┘
Отже, остаточно, структура rec в пам’яті комп’ютера в 16-ковій системі числення зберігається в 32 байтах в такому вигляді:
00 00 00 00 00 00 00 40 6D 79 00 00 00 CC CC CC 04 00 00 00 05 00 00 00 01 39 CC CC CC CC CC CC
В процесі програмування неминуче виникає проблема економії простору пам'яті.
На рівні типів даних є два способи вирішення цієї проблеми:
1) розміщення в байті більше одного невеликого об'єкта;
2) використання одного й того ж простору для зберігання різних об'єктів у різний час.
Першого можна досягти за допомогою використання бітових полів, другого - через використання об'єднань