Вступ Теоретична частина Масив - це впорядкований скінченний набір даних одного типу, які зберігаються в послідовно розташованих комірках оперативної пам'яті і мають спільну назву. З оголошення масиву компілятор одержує інформацію про тип елементів масиву та їх кількість. Якщо початкових значень меньше, ніж елементів в масиві, то елементам, що залишились автоматично надаються нульові початкові значення. Наприклад, елементам масиву b можна присвоїти нульові початкові значення за допомогою оголошення int b[12] = {3, 2, 1}; яке явно надає початкові значення першим трьом елементам масиву і неявно надає нульові початкові значення решті дев’яти елементам, оскільки початкових значень меньше, ніж оголошено елементів масиву. Однак, по замовчуванню автоматично масив не отримує нульові початкові значення неявно. Треба присвоїти нульові початкові значення хоча б першому елементу для того, щоб автоматично були обнулені всі решта елементів, наприклад: int b[5] = {0}; // аналогічно присвоєнням : b[0]=0; b[l]=0; b[2]=0; b[3]=0; b[4]=0; Синтаксичною помилкою буде задання в списку більшої кількості початкових значень, ніж є елементів в масиві. Наприклад, оголошення масиву int b[5] = {5, 4, 3, 2, 1, 0}; призведе до синтаксичної помилки, оскільки список ініціалізації містить 6 початкових значень, а масив має тільки 5 елементів. Багатовимірні масиви компілятор розглядає як послідовність одновимірних, тому до елементів такого масиву, як і для одновимірних, можна також звертатись через вказівники. В пам'яті комп'ютера елементи масиву з першого до останнього запам'ятовуються в послідовних зростаючих комірках пам'яті. Між елементами масиву в пам'яті розриви відсутні. Елементи масиву з найменшим індексом зберігаються по найменшій адресі пам’яті. Багатовимірні масиви в пам'яті комп'ютера зберігаються так, що найбільш правий індекс збільшується першим. Приклад 8. Розглянемо двовимірний масив цілих чисел: іnt mass [3][2]= { {1, 1}, {0, 2}, {1, 3} }; В пам’яті комп’ютера він зберігається у такому виді: 00000001 00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000000 mass [0][0] mass [0][1] 00000000 00000000 00000000 00000010 00000000 00000000 00000000 00000001 00000000 mass [1][0] mass [1][1] 00000000 00000000 00000011 00000000 00000000 00000000 mass [2][0] mass [2][1] Структура. На відміну від масиву, всі елементи якого однотипні, структура може містити елементи різних типів. В мові C++ структура є видом класу і має всі його властивості, але в багатьох випадках доситатньо використовувати структури так, як вони визначені в мові С: struct [ім'я_типу] { тип_1 елемент _1: тип_2 елемент _2; тип_n елемент _n; } [ список_оголошень ]; Елементом структури може бути бітове поле, що забезпечує доступ до окремих бітів пам'яті. Поза структурами бітові поля використовувати не можна. Бітові поля - це особливий вид полів структури. Вони використовуються для щільного упакування даних, наприклад, прапорців типу "так/ні". Найменьша по довжині комірка пам'яті, яку можна адресувати - 1 байт, а для збереження прапорця досить одного біта. При описі бітового поля після імені через двокрапку вказується довжина поля в бітах, що задається цілим виразом або константою. Поле нульової довжини означає вирівнювання на границю наступного слова. Допускаються неіменовані поля бітів. Вони не впливають на зміст іменованих полів, але певним чином можуть поліпшувати розміщення полів в пам'яті. Структури бітових полів можуть містити і знакові елементи. Але, навіть цілі поля можуть розглядатись як беззнакові. Тому рекомендується описувати бітові поля як unsіgned. В пам'яті бітові поля розміщуються на відповідних границях слів, при цьому деякі біти слів можуть залишатись невикористаними. Поле, яке не можна розмістити у місце, що залишилося до границі слова, розміщується в наступне слово. Поле не може бути ширшим за слово. На деяких машинах бітові поля розміщуються справа наліво, а на деяких – зліва направо. Об'єднання дуже схожі на структури. Однак на відміну від структури об'єднання зберігає значення тільки одного елемента в кожний момент часу. Інакше кажучи, коли виконується операція присвоювання значення елементу об'єднання, то перезаписується будь-яке попереднє присвоювання. Головною особливістю об'єднання є те, що для кожного з оголошених елементів виділяється та сама область пам'яті, тобто вони перекриваються. Пам'ять, що відповідає змінній типу об'єднання, визначається величиною, необхідною для розміщення найбільш довгого елемента об'єднання. Коли використовується елемент меншої довжини, то змінна типу об'єднання може містити зайву пам'ять, що не використовується. Всі елементи об'єднання зберігаються в одній і тій cамій області пам'яті, починаючи з однієї адреси. Алгоритм розв’язання задачі. Рішення задачі проводимо за допомогою шаблону функції, що дає змогу працювати з усіма стандартними типами даних. В функції оголошуємо вказівник на змінну типу “unsigned char” і присвоюємо їй адресу змінної, яку необхідно прочитати. Побайтно зчитуємо дані з пам’яті і виводимо їх в шіснадцятковій системі численя, також виводимо десяткове значення змінної. В головній програмі оголошуємо необхідні змінні і виводимо результати роботи програми. 3. Система тестів Завдання 1: Внутрішні формати базових типів Визначити внутрішнє представлення в пам’яті комп’ютера даних базових типів. Розглянути основні прості (цілі, дійсні, символьні, логічні) типи даних: bool b; char ch1; unsigned i3; long double d3; 3.1.1. Логічний тип Тестування проводимо для наступних значень змінних: b = (день народження * 5) % 10 * місяць народження = (6 * 5) % 10 * 1 = 30 % 10 = 0; Змінна типу bool займає в пам’яті комп’ютера 1 біт і коли змінна приймає значення відмінне від 0, то ВПК записується «1», а якщо 0, то ВПК 0. Оскільки b = 0, то ВПК (b) – 0 3.1.2. Символьний тип Для надання значень символьним змінним використати одну з літер Прізвища (латинські літери, перша - велика, решта - малі). Якщо прізвище містить менше трьох літер, то замість відсутніх символів записати нулі. ch1 = перша літера прізвища = ‘G’; Змінна типу char займає в пам’яті комп’ютера 1 байт. ASCII код великої латинської літери G – 7110. Для отримання значення змінної ВПК, необхідно перевести це число до двійкової СЧ. 7110 = 0100 01112. Оскільки char займає 1 байт, то «перевертання» числа побайтно не впливає на його зміст. Отже, ВПК (ch1) – 0100 0111 в двійковії СЧ, або 47 в шістнадцятковій СЧ. 3.1.3. Цілий тип i3 = день народження * 215 = 6 * 215 = 1290; Змінна типу int займає в пам’яті комп’ютера 4 байти. Для того, щоб визначити внутрішнє представлення в пам’яті комп’ютера цього числа, його спочатку треба перевести у двійкову СЧ, оскільки додатні цілі числа зберігаються у прямому двійковому коді. 129010 = 101 0000 10102. Доповнимо це число зліва нулями до 4 байт (32 біт/32 розряди): 0000 0000 0000 0000 0000 0101 0000 1010. Тепер для отримання значення числа ВПК, необхідно обернути його побайтно, бо ВПК цілі числа зберігаються у зворотньому порядку розміщення байт числа:
Отже, ВПК (i3) – 0000 1010 0000 0101 0000 0000 0000 0000 у 2 СЧ, або 0A05000 у 16 СЧ. 3.1.4. Дійсний тип Для надання значень дійсним змінним використати такі позначення: X – день народження, Y – місяць народження, Z = X * Y; Х = 6; Y = 1; Z = X * Y = 6 * 1 = 6; d3 = – Z . X e Y; d3 = – 6.6 e 1 = - 6.6 * 101 = - 66; Переведем число у 16 та 2 СЧ: -6610 = -4216 = -10000102 Необхідно визначити значення m (мантиса), s(знак) та e(експонента). s = 1, бо число від’ємне. 1000010,0 нормалізація.. 1,000010 * 10110 long double займає ВПК 10 байт (80 біт/80 двійкових розрядів) З них 15 біт виділяється під експоненту, 1 біт під знак числа і решта 64 під мантису (у long double числі мантиса берется з початковою одиницею.). Експонента: 6 = e - 16383. е = 1638910 = 100 0000 0000 01012 Нам необхідно визначити перші 63 двійкових розрядів мантиси: 00001 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 000 Зборка за схемою: S e 1 m
1100 0000 0000 0101 1000 0100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00002 = C0 05 84 00 00 00 00 00 00 0016 Тепер для отримання значення числа ВПК, необхідно обернути його побайтно, бо ВПК long double числа зберігаються у зворотньому порядку розміщення байт числа: Отже, ВПК (d3) - 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0100 0000 0101 1100 00002 = 00 00 00 00 00 00 00 84 05 C016 * Розмір типу long double для різних компіляторів може відрізнятися, наприклад для BCB 6.0 буде займати 10 байт, для VC++ 6.0 буде займати 8 байт (в цьому випадку формат збереження типу long double співпадає з форматом типу double). Мій компілятор признає long double числа як простий double. Завдання 2: Внутрішні формати похідних типів 3.2.1. Рядок символів Визначити представлення в пам’яті комп’ютера рядків символів. № варіанта = (((день народження * номер будинку) % номер квартири) * * місяць народження + номер будинку) % 30 = (((6 * 12) % 72) * 1 + 12) = (0+12) = 12. Тестування провести для наступних значень змінних Оголосити рядок символів і ініціалізувати його згідно наведеній нижче таблиці. Після цього виконати деякі переприсвоювання, задані після таблиці. char *string12 = "erjf\45\\h\54\x3\\nn\\f\xf\n" """gh"; «Розберемо» цей рядок:
Х 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
string12[X] e r j f % \ h ,
\ n n \ f
LF g h
У 16 СЧ 65 72 6A 66 37 2F 68 44 03 2F 6E 6E 2F 66 0F 00 0A 67 68
LF- Line Feed Виконуємо наступні переприсвоюння: string12 [00] = символ, що відповідає 03 цифрі номера мобільного телефона = ‘3’; string12 [02] = символ, що відповідає 04 цифрі номера мобільного телефона = ‘6’; string12 [04] = символ, що відповідає 05 цифрі номера мобільного телефона = ‘2’; string12 [06] = символ, що відповідає 06 цифрі номера мобільного телефона = ‘5’; string12 [08] = символ, що відповідає 07 цифрі номера мобільного телефона = ‘4’; string12 [10] = символ, що відповідає 08 цифрі номера мобільного телефона = ‘6’; string12 [12] = символ, що відповідає 09 цифрі номера мобільного телефона = ‘7’; string12 [14] = символ, що відповідає 10 цифрі номера мобільного телефона = ‘4’; Х 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
В результаті рядок символів набуде такого вигляду: char *string12 = "3r6f2\\5,4\\6n7f4\ngh”; Переведем у 16 СЧ (значення рядка): довжина радка – 20 байт. ВПК string12: 33 72 36 66 32 2F 35 44 34 2F 36 6E 37 66 34 0A 0A 67 68 00 3.2.2. Представлення перерахувань Визначити представлення в пам’яті комп’ютера перерахувань. № варіанта = ((день народження + номер будинку) * (номер квартири + місяць народження)) % 30 = ((6 + 12) * (72 + 1)) % 30 = 1314 % 30 = 24. Оголосити три змінні перераховного типу і надати їм значення згідно наведеній нижче таблиці. enum color24 { BLUE, // 0, бо не визначено (немає присвоєння значення змінній BLUE) GREEN, // 1, (оскільки невизначено, то GREEN = BLUE + 1) CYAN = 3, // 3, бо вказано (змінній CYAN присвоєно значення 3) RED, // 4, (оскільки невизначено, то RED = CYAN + 1) BROWN, // 5, (оскільки невизначено, то BROWN = RED + 1) GRAY = -2, // -2, бо вказано (змінній GRAY присвоєно значення -2) YELLOW, // -1, (оскільки невизначено, то YELLOW = GRAY + 1) WHІTE, // 0, (оскільки невизначено, то WHITE = YELLOW + 1) MAGENTA = 1, // 1, бо вказано (змінній MAGENTA присвоєно значення 1) LІGHTGRAY, // 2, (оскільки невизначено, то LIGHTGRAY = MAGENTA + 1) DARKGRAY, // 3, (оскільки невизначено, то DARKGRAY = LIGHTGRAY + 1) BLACK // 4, (оскільки невизначено, то BLACK = DARKGRAY + 1) } c1= CYAN, // c1 = CYAN = 3; c2= BROWN, // c2 = BROWN = 5; c3= DARKGRAY; // c3 = DARKGRAY = 3; ВПК c1: 03 00 00 00 ВПК c2: 05 00 00 00 ВПК c3: 03 00 00 00 3.2.3. Представлення масивів Визначити представлення в пам’яті комп’ютера масивів. № варіанта = (номер будинку * 10 + номер квартири * місяць народження) % 30 = (12 * 10 + 72 * 1) % 30 = 192 % 30 = 12. Оголосити масив та ініціалізувати його згідно наведеній нижче таблиці. Після цього виконати деякі переприсвоювання, задані після таблиці. char array12[][2][3] = {{2,56}, {6,}, {{3,8,1}}}; Оскільки всередині головних фігурних дужок знаходяться 3 пари другорядних, то це означає що розмірність масиву array12[3][2][3]. array12 = {{{{2},{56},{0}},{{0},{0},{0}}},{{{6},{0},{0}},{{0},{0},{0}}},{{{3},{8},{1}},{{0},{0},{0}}}}; array12[0][0][0] = 2; array12[0][0][1] = 56; array12[0][0][2] = 0; array12[0][1][0] = 0; array12[0][1][1] = 0; array12[0][1][2] = 0; array12[1][0][0] = 6; array12[1][0][1] = 0; array12[1][0][2] = 0; array12[1][1][0] = 0; array12[1][1][1] = 0; array12[1][1][2] = 0; array12[2][0][0] = 3; array12[2][0][1] = 8; array12[2][0][2] = 1; array12[2][1][0] = 0; array12[2][1][1] = 0; array12[2][1][2] = 0; Отже його можна представити у табличному вигляді так:
Виконую наступні переприсвоюння: 1-ий елемент масиву = (01 цифра номера мобільного телефона) * (на день народження) = 0; 2-ий елемент масиву = (02 цифра номера мобільного телефона) * (на день народження) = 54; 3-ий елемент масиву = (03 цифра номера мобільного телефона) * (на день народження) = 18; 4-ий елемент масиву = (04 цифра номера мобільного телефона) * (на день народження) = 36; 5-ий елемент масиву = (05 цифра номера мобільного телефона) * (на день народження) = 12; 6-ий елемент масиву = (06 цифра номера мобільного телефона) * (на день народження) = 30; 7-ий елемент масиву = (07 цифра номера мобільного телефона) * (на день народження) = 24; 8-ий елемент масиву = (08 цифра номера мобільного телефона) * (на день народження) = 36; 9-ий елемент масиву = (09 цифра номера мобільного телефона) * (на день народження) = 42; 10-й елемент масиву = (10 цифра номера мобільного телефона) * (на день народження) = 24; array12 = {{{{0},{54},{18}},{{36},{12},{30}}},{{{24},{36},{42},{{24},{0},{0}}},{{{3},{8},{1}},{{0},{0},{0}}}}; array12[0][0][0] = 0; array12[0][0][1] = 54; array12[0][0][2] = 18; ВПК array12[0][0][0] = 00; ВПК array12[0][0][1] = 36; ВПК array12[0][0][2] = 12; array12[0][1][0] = 36; array12[0][1][1] = 12; array12[0][1][2] = 30; ВПК array12[0][1][0] = 24; ВПК array12[0][1][1] = 0C; ВПК array12[0][1][2] = 1E; array12[1][0][0] = 24; array12[1][0][1] = 36; array12[1][0][2] = 42; ВПК array12[1][0][0] = 18; ВПК array12[1][0][1] = 24; ВПК array12[1][0][2] = 2A; array12[1][1][0] = 24; array12[1][1][1] = 0; array12[1][1][2] = 0; ВПК array12[1][1][0] = 18; ВПК array12[1][1][1] = 00; ВПК array12[1][1][2] = 00; array12[2][0][0] = 3; array12[2][0][1] = 8; array12[2][0][2] = 1; ВПК array12[2][0][0] = 03; ВПК array12[2][0][1] = 08; ВПК array0[2][0][2] = 01; array12[2][1][0] = 0; array12[2][1][1] = 0; array12[2][1][2] = 0; ВПК array12[2][1][0] = 00; ВПК array12[2][1][1] = 00; ВПК array12[2][1][2] = 00; Отже, ВПК array12: 00 36 12 24 0С 1E 18 24 2A 18 00 00 03 08 01 00 00 00 Масив можна представити у табличному вигляді так:
3.2.4. Представлення структур Визначити представлення в пам’яті комп’ютера структур. № варіанта = (день народження * 3 * номер квартири + (місяць народження % 3) * номер будинку) % 30 = (6 * 3 * 72 + (1 % 3) * 12) % 30 = 1308 % 30 = 18. Оголосити структуру згідно наведеній нижче таблиці. Після цього надати всім елементам структури певні значення, задані після таблиці. struct str18 { float a; // Займає ВПК 4 байт unsigned e:6; // Займає ВПК 6 біт signed long b:9; // Займає ВПК 9 біт // Оскільки далі нема бітового поля, то незаповнені байти // заповняться з 15 біт до 4 байт. (вирівнювання) char c[10]; // Займає ВПК 1*10 = 10 байт short d; // Займає ВПК 2 байт long :3; // Займає 3 біт // Оскільки далі нема бітового поля, то незаповнені байти // заповняться з 3 біт до 4 байт. (вирівнювання) wchar_t f; // Займає 2 байт signed :4; // Займає 4 біт // Оскільки далі нема бітового поля, то незаповнені байти // заповняться з 4 біт до 6 байт. (вирівнювання) }str; “:6” “:9” “:3” “:4” – бітові поля - показують компілятору, скільки біт виділяється на дану змінну структури. Разом структура займатиме 4+2+20+2+1+2+1 = 32 байт. Номер байту 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Значення СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС
Значення СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС
Число C8 C9 d long :3 f signed :4
На даному етапі ВПК структури заповнене 32 однаковими байтами СС, оскільки вона ще пуста. Виконую надання значень елементам структури : 1) str.a = D.DM = 6,6; Перші 4 байта структури заповнюються представленням ВПК float числа а: ВПК а(6,6): 33 33 D3 40 Номер байту 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Значення 33 33 D3 40 СС СС СС СС СС СС СС СС СС СС СС СС
Значення СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС
Число C8 C9 d long :3 f signed :4
2) str.b = BD * KV * 124 = 12 * 72 * 124 = 107136; На деяких машинах бітові поля розміщуються справа наліво, а на деяких – зліва направо. Приймемо, що бітові поля розміщуються справа наліво. Розглянемо детальніше 5 та 6 байти структури: e займає 6 біт, і оскільки бітові поля розміщуються справа наліво, то біти з кінця 5 байта (8 біт) до 3 біта (разом 6 комірок) зарезервуються для числа е. Останні 2 байти ВПК числа b запишуться в комірки бітів 1 та 2, оскільки бітові поля розміщуються справа наліво. Решта числа b запишеться в 6 байті. ВПК b = 107136: 80 A2 01 0016= 1000 0000 1010 0010 0000 0001 0000 00002 Число записується побайтово, тому спочатку запишеться перший байт 1000 0000. Його останні 2 біта увійдуть до перших двох комірок. Решта 6 біт запишется у комірки 11-16. Далі записуватиметься другий байт числа b 1010 0010. Під число b зарезервовано 9 біт, ми вже використали 8. Тому запишеться ще 1 біт (підкреслений). Незаповнена зона (під число е і -) не зміниться (пуста структура – СССС….СССС) Біти 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Значення 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0
Число b e - b
3) str.c[0] = перша літера = ‘G’; str.c[1] = друга літера = ‘r’; str.c[2] = третя літера = ‘o’; str.c[3] = четверта літера = ‘m’; str.c[4] = п'ята літера = ‘o’; Після такого надання значень ВПК масиву с[] буде таким: 47 72 6F 6D 6F CC CC CC CC CC Під масив с[] зарезервовано в структурі байти 9 – 18. Туди запишеться ВПК масиву: Номер байту 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Значення 33 33 D3 40 0С A0 CC CC 47 72 6F 6D 6F СС СС СС
Значення СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС СС
Число C8 C9 d long :3 f signed :4
4) str.d = 764 * BD * Х = 764 * 12 * 2 = 18336; ВПК число d типу short представляється так: A0 47. Це значення запишеться в байти 19-20 структури, оскільки там зарезервовано змінну d. 5) str.e = DN * MN * 36 = 6 * 1 * 36 = 216; ВПК число e типу unsigned представляється так: D8 00 00 00. Під число е в структурі зарезервовано 6 біт. Це менше 1 байта, тому до уваги берется тільки перший байт числа е 1101 1000. Шість останніх бітів з цього байту (01 1000) впишуться в шість останніх бітів 5 байта структури. Біти 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Значення 0 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0
Число b e - b
Тепер сформувалося остаточне значення 5 та 6 байтів структури – 0001 1000 1010 0000. 7 та 8 байти будуть пустими (СС СС) через вирівнювання по довжині слова. 6) str.f = Y = 4; ВПК число f типу wchar_f представляється так: 04 00. Це значення запишеться в байти 25-26 структури, оскільки там зарезервовано змінну f. Тепер, провівши всі операції ми маємо остаточне представлення структури в пам’яті комп’ютера: Номер байту 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Значення 33 33 D3 40 18 A0 CC CC 47 72 6F 6D 6F СС СС СС
Значення СС СС A0 47 СС СС СС СС 04 00 СC СС СС СС СС СС
Число C8 C9 d long :3 f signed :4
Структура ВПК: 33 33 D3 40 18 A0 CC CC 47 72 6F 6D 6F CC CC CC CC CC A0 47 CC CC CC CC 04 00 CC CC CC CC CC CC 3.2.5. Представлення об'єднань Визначити представлення в пам’яті комп’ютера об'єднань. № варіанта = (день народження + місяць народження + номер квартири * номер будинку + день народження * місяць народження) % 30 = (6 + 1 + 72 * 12 + 6 * 1) % 30 = 877 % 30 = 7. Оголосити об'єднання згідно наведеній нижче таблиці. Після цього надати деяким елементам об'єднання початкові значення, задані після таблиці. union un7 { int b; struct { float f[2]; wchar_t a[6]; }; struct { char d[5]; float e; }; int c; } un; Виконую надання значень елементам об'єднання : un.e = KV * 325 + YEAR * DN = 72*325 + 1993*6 = 23400 + 11958 = 35358; un.c = DN * (MN + BD) * 100 = 6 * (1 + 12) * 100 = 7800; un.a[0] = символ, що відповідає 06 цифрі номера мобільного телефона = ‘5’; un.a[1] = символ, що відповідає 07 цифрі номера мобільного телефона = ‘4’; un.a[2] = символ, що відповідає 08 цифрі номера мобільного телефона = ‘6’; un.a[3] = символ, що відповідає 09 цифрі номера мобільного телефона = ‘7’; un.a[4] = символ, що відповідає 10 цифрі номера мобільного телефона = ‘4’; Визначимо представлення в пам'яті комп’ютера окремо кожного елемента об'єднання: 1) int b; ВПК змінна типу int займає 4 байти. Змінній не надано значення. 2) struct { float f[2]; // Займає ВПК 4 * 2 = 8 байт wchar_t a[6]; // Займає ВПК 2 * 6 = 12 байт }; Оскільки float f[2] займає ВПК 4 * 2 = 8 байт, то тут не потрібне вирівнювання до повного слова. Ця структура займає ВПК 8 + 12 = 20 байт. Масиву f не надано ніякого значення, тому його представлення ВПК таке: СС СС СС СС СС СС СС СС. Масиву а надані такі значення: a[0] = ‘5’; // ВПК: 35 00 a[1] = ‘4’; // ВПК: 34 00 a[2] = ‘6’; // ВПК: 36 00 a[3] = ‘7’; // ВПК: 37 00 a[4] = ‘4’; // ВПК: 34 00 Представлення масиву а[] ВПК: 35 00 34 00 36 00 37 00 34 00 СС СС. Звідси, представлення структури ВПК: СС СС СС СС СС СС СС СС 35 00 34 00 36 00 37 00 34 00 СС СС 3) struct { char d[5]; // Займає ВПК 1 * 5 = 5 байт float e; // Займає ВПК 4 байт }; Оскільки char d[5] займає 5 байт, то тут буде присутнєвирівнювання до повного слова. Тому ця структура займатиме ВПК 5 + 3 + 4 = 12 байт. Масиву char d[5] не надано ніякого значення, тому його представлення ВПК таке: СС СС СС СС СС Змінній е надано таке значення: e = 35358; ВПК змінна е представляється як: 00 1E 0A 47. Звідси, представлення структури ВПК: СС СС СС СС СС СС СС СС 00 1E 0A 47 4) int c; ВПК змінна типу int займає 4 байти. Змінній с надано значення: c = 7800; ВПК с: 78 1E 00 00 Величиною, необхідною для розміщення найбільш довгого елемента об'єднання є перша структура, під яку виділяється 20 байт. - Після виконання першої операції присвоєння un.e = 35358; в цих 20 байтах пам’яті в 16- ковій системі числення буде записана така послідовність: СС СС СС СС СС СС СС СС 00 1E 0A 47 СС СС СС СС СС СС СС СС - Після виконання другої операції присвоєння un.c = 7800; перші 4 байта пам’яті будуть переписані і в результаті в пам’яті в 16- ковій системі числення буде записана така послідовність: 78 1E 00 00 СС СС СС СС 00 1E 0A 47 СС СС СС СС СС СС СС СС - Наступна операція: un.a[0] = '5'; Тільки визначені 2 байти з 20 (СС СС СС СС СС СС СС СС 35 00 СС СС СС СС СС СС СС СС СС СС) пам’яті будуть переписані: 78 1E 00 00 СС СС СС СС 35 00 0A 47 СС СС СС СС СС СС СС СС - Наступна операція: un.a[1] = '4'; Тільки визначені 4 байти з 20 (СС СС СС СС СС СС СС СС 35 00 34 00 СС СС СС СС СС СС СС СС) пам’яті будуть переписані: 78 1E 00 00 СС СС СС СС 35 00 34 00 СС СС СС СС СС СС СС СС - Наступна операція: un.a[2] = '6'; Тільки визначені 6 байт з 20 (СС СС СС СС СС СС СС СС 35 00 34 00 36 00 СС СС СС СС СС СС) пам’яті будуть переписані: 78 1E 00 00 СС СС СС СС 35 00 34 00 36 00 СС СС СС СС СС СС - Наступна операція: un.a[3] = '7'; Тільки визначені 8 байт з 20 (СС СС СС СС СС СС СС СС 35 00 34 00 36 00 37 00 СС СС СС СС) пам’яті будуть переписані: 78 1E 00 00 СС СС СС СС 35 00 34 00 36 00 37 00 СС СС СС СС - Наступна операція: un.a[4] = '4'; Тільки визначені 8 байт з 20 (СС СС СС СС СС СС СС СС 35 00 34 00 36 00 37 00 34 00 СС СС) пам’яті будуть переписані: Остаточне представлення об’єднання ВПК: 78 1E 00 00 СС СС СС СС 35 00 34 00 36 00 37 00 34 00 СС СС 4. Результати виконання програми:
Висновки: Виконуючи цю розрахункову роботу я повторив, як визначити внутрішнє представлення цілих, дійсних, логічних та символьних чисел в пам’яті комп’ютера. Також я довідався багато нового про представлення в пам’яті комп’ютера рядків символів, перерахувань, масивів, структур та об’єднань. Список літератури: Лисак Т. А. Основи представлення данних в пам'яті комп'ютера: Конспект лекцій (частина І ) з дисципліни “Програмування. Частина IIІ. Структури даних та алгоритми". – Львів: Видавництво НУ “Львівська політехніка”, 2010 – 37 с. Конспект лекцій. Додатки: #include <stdio.h> #include <conio.h> #include <iostream> using namespace std; int main (void) { setlocale(0, ""); // Ввід кирилиці cout << " ЗАВДАННЯ 1:" << endl; cout << " 1.1 Логiчний тип" << endl; bool b; b = 0; unsigned char *b_1 = (unsigned char *)(&b); for (int i = 0; i < sizeof(b); i++) printf("%02X ", b_1[i]); cout << endl; cout << " 1.2 Символьний тип" << endl; char ch1; ch1 = 'G'; unsigned char *ch1_1 = (unsigned char *)(&ch1); for (int i = 0; i < sizeof(ch1); i++) printf("%02X ", ch1_1[i]); cout << endl; cout << " 1.3 Цiлий тип" << endl; unsigned i3; i3 = 1290; unsigned char *i3_1 = (unsigned char *)(&i3); for (int i = 0; i < sizeof(i3); i++) printf("%02X ", i3_1[i]); cout << endl;