2. Масиви, рядки, покажчики.
Масив являє собою агрегат з декількох змінних одного і того ж типу. Масив з ім'ям a з LENGTH елементів типу TYPE оголошується так:
Це відповідає тому, що оголошуються змінні типу TYPE зі спеціальними іменами a [0], a [1]. a [LENGTH -1]. Кожен елемент масиву має свій номер - індекс. Доступ до x -ому елементу масиву здійснюється за допомогою операції індексації:
В якості індексу може використовуватися будь-який вираз, котре видає значення цілого типу: char. short. int. long. Індекси елементів масиву в Сі починаються з 0 (а не з 1), і індекс останнього елемента масиву з LENGTH елементів - це LENGTH -1 (а не LENGTH). Тому цикл по всіх елементах масиву - це
indx Статичні масиви можна оголошувати з ініціалізацією. перераховуючи значення їх елементів в <> через кому. Якщо задано менше елементів, ніж довжина масиву інші елементи вважаються нулями: Якщо при описі масиву з ініціалізацією й вказати його розмір, він буде підрахований компілятором: Вказівником можна привласнити значення іншого покажчика на такий же тип. В результаті обидва покажчика вказуватимуть на одне і те ж місце в пам'яті: ptr1 = ptr; Ми можемо змінювати указуемую змінну за допомогою операції * В даному випадку ми заносимо і потім читаємо значення змінної array [x], на яку поставлений покажчик, тобто Операція * пояснює сенс опису TYPE * ptr; воно означає, що значення виразу * ptr матиме тип TYPE. Назва ж типу самого покажчика - це (TYPE *). Зокрема, TYPE може сам бути вказівним типом - можна оголосити покажчик на покажчик, на кшталт char ** ptrptr; Таке спорідненість покажчиків і масивів дозволяє нам застосовувати операцію * до імені масиву: value = * array; означає те ж саме, що і value = array [0]; Відзначимо, що покажчик можна направити в неправильне місце - на ділянку пам'яті, що містить дані не того типу, який заданий в описі покажчика; або взагалі містить невідомо що: Саме присвоювання вказівником некоректного значення ще не є помилкою. Помилка виникне лише при зверненні до даних з цього вказівником (такі помилки досить важко шукати!). sizeof (arr [0]) видає розмір одного елемента. І все це не залежить від типу елемента (просто тому, що всі елементи масивів мають однаковий розмір). З масивами байт можна використовувати наступну конструкцію, що задає масиви (рядки) однакового розміру: В даному розділі ми в основному будемо розглядати рядки і покажчики на символи. Яким чином започатковано за замовчуванням зовнішні і статичні масиви? Ініціалізувалися чи за замовчуванням автоматичні масиви? Яким чином можна присвоювати значення елементів масиву, що відноситься до будь-якого класу пам'яті? Нехай заданий масив int arr [10]; що тоді означають вирази: Чи правильно написано збільшення величини, на яку вказує покажчик a. на одиницю? Відповідь: ні, треба: Дан фрагмент тексту: Чому рівні (Відповідь: 'x', '\ 0', 'd') Чи можна написати a ++. Те ж про b ++. Чи можна написати b = a. a = b. (Немає, так, так, немає) Нижче наведена програма, що обчислює середнє значення елементів масиву Перепишіть зазначену програму із застосуванням покажчиків. Що друкується в результаті роботи програми? Чому масив arr [] описаний поза функції main ()? Як внести його в функцію main (). Відповідь: написати всередині main Чи можна писати на Сі так: Відповідь: на жаль не можна (Сі - це не Algol). При відведенні пам'яті для масиву в якості розміру повинна бути вказана константа або вираз, яке може бути ще під час компіляції обчислено до целочисленной константи, тобто масиви мають фіксовану довжину. Складіть програму ініціалізації двовимірного масиву a [10] [10], вибірки елементів з a [5] [5] до a [9] [9] і їх роздруківки. Використовуйте доступ до елементів за вказівником. Складіть функцію обчислення скалярного добутку двох векторів. Довжина векторів задається в якості одного з аргументів. Складіть функцію множення двовимірних матриць a [] [] * b [] []. Складіть функцію множення тривимірних матриць a [] [] [] * b [] [] []. Для тих, хто програмував на мові Pascal. яка допущена помилка? Відповідь: багатовимірні масиви в Сі треба індексувати так: У написаному ж прикладі ми маємо в якості індексу вираз x, y (оператор "кома") зі значенням y. тобто Синтаксичної помилки немає, але сенс абсолютно змінився! Двовимірні масиви в пам'яті представляються як одномірні. Наприклад, якщо то конструкція a [y] [x] перетворюється при компіляції в одновимірну конструкцію, подібну такий: тобто Наслідком цього є те, що компілятор для генерації індексації двовимірних (і більше) масової повинен знати M - розмір масиву по 2-го виміру (а також 3-ним, 4-му, і.т.д.). Зокрема, при передачі багатовимірного масиву в функцію А також при описі зовнішніх масивів: Ось як, наприклад, повинна виглядати робота з двовимірним масивом arr [ROWS] [COLS], відведеним за допомогою malloc (); Як описувати посилання (покажчики) на двовимірні масиви? Розглянемо таку програму: Покажчиком тут є ptr. Відзначимо, що у нього задана розмірність по другому виміру: Second. саме для того, щоб компілятор міг правильно обчислити двовимірні індекси. Спробуйте самі оголосити і побачити, до яких невеселим ефектів це призведе (компілятор, до речі, буде лаятися, але є ймовірність, що він все ж странслірует це для вас. Але працювати воно буде плачевно). Спробуйте також використовувати ptr [x] [y]. Що означають опису? Змінні в Сі описуються в форматі їх використання. Так опис означає, що f можна використовувати у вигляді Однак з такого способу опису тип самої описуваної змінної і його сенс досить неочевидні. Наведемо прийом (запозичений з журналу "Communications ofthe ACM"), що дозволяє прояснити сенс опису. Опис на Сі перекладається в опис в стилі мови Algol-68. Далі Наведемо кілька прикладів, з яких ясний і спосіб перетворення: тобто f - функція, яка повертає покажчик на функцію, що повертає ціле. f - масив покажчиків на функції, які повертають цілі. Зворотно: опишемо Напишіть функцію strcat (d, s), приписують рядок s до кінця рядка d. Відповідь: Цикл, позначений "strcpy" - це найбільш короткий запис операторів Насправді strcat повинен за стандартом повертати свій перший аргумент, як і функція strcpy. Ці два варіанти демонструють, що функція може бути реалізована різними способами. Крім того видно, що замість стандартної бібліотечної функції ми можемо визначити свою однойменну функцію, кілька відрізняється поведінкою від стандартної (як повертається значення в 1-му варіанті).
g як покажчик на функцію, яка повертає покажчик на масив з 5і покажчиків на функції, які повертають покажчики на цілі. У Сі неможливі функції, які повертають масив: Сама назва типу (наприклад, для використання в операції приведення типу) виходить викреслюванням імені змінної (а також можна опустити розмір масиву):Схожі статті