- •2. Основні елементи мови с
- •3.1 Алфавіт мови програмування
- •3.2Лексеми
- •3.3Ключові слова
- •3.4Ідентифікатори
- •3.5 Класифікація типів даних
- •3.6 Літерали
- •3.7 Оператори
- •3.8 Коментарі
- •3.9 Директиви препроцесора
- •3.10 Організація програми
- •3. Операції та вирази
- •4.1 Загальні відомості
- •4.2 Арифметичні операції
- •4.3 Операції приведення типів
- •(Тип) ідентифікатор,
- •4.4 Операції присвоєння
- •4.5 Операції інкремента і декремента
- •4.6 Операції порівняння
- •4.7 Операції зсуву
- •4.8 Порозрядні операції
- •4.9 Логічні операції
- •4.10 Операція sizeof
- •Sizeof ( Вираз ),
- •4.11 Операція послідовного обчислення
- •4.12 Операція умови (?:)
- •Операнд-1 ? Операнд-2 : Операнд-3
- •4.13 Адресні операції
- •Тип * ім'я_покажчика;
- •4. Прості типи даних
- •5.1 Оголошення змінних
- •[ Модифікатори ] тип ім’я_змінної;
- •5.2 Час існування та область видимості змінних
- •5.3 Цілі типи даних
- •5.4 Дійсні типи даних
- •5. Оператори керування
- •5.1 Оператор розгалуження if
- •If ( Вираз ) true-оператор;
- •5.2 Оператор розгалуження if-else
- •If ( Вираз ) true-оператор; else false-оператор;
- •5.3 Оператор множинного розгалуження switch
- •5.4 Оператор циклу for
- •For ( Вираз 1 ; Вираз 2 ; Вираз 3 ) тіло циклу
- •5.5 Оператор циклу while
- •While ( Вираз ) тіло циклу
- •5.6 Оператор циклу do while
- •Тіло циклу while ( Вираз ) ;
- •5.7 Оператор break
- •5.8 Оператор continue
- •6 Введення та виведення даних
- •7.1 Функція виведення printf
- •Int printf( стрічка форматування, змінна1, змінна2, ... );
- •7.2Функція введення scanf
- •Int scanf (стрічка форматування, адреса змінної1, адреса змінної2, ... );
- •9.1 Введення та виведення у файл
- •7 Масиви
- •7.1 Загальні поняття
- •7.2 Одновимірні масиви
- •Тип даних ім’я змінної [n];
- •7.3 Багатовимірні масиви
- •6. Функції
- •6.1 Основні поняття
- •{Тіло функції}
- •6.2 Область видимості
- •6.3 Порожній тип void
- •6.4 Передача аргументів у функцію
- •6.5 Рекурсивні функції
- •6.6 Прототипи функцій
- •8. Рядки в с
- •4.1 Прототипи
- •4.2 Функції перетворення буферів
- •4.3 Функції перевірки літер
- •4.4 Рядок символів
- •4.5 Операції з рядками:
- •4.6 Символьні константи
- •9. Покажчики
- •5.1 Визначення та ініціалізація покажчиків
- •5.2 Визначення покажчиків:
- •5.3 Масиви
- •5.6 Копіювання рядка
- •5.7 Посилання та оператор &
- •5.9 Посилання в якості результатів функції
- •5.10 Покажчики на функцію
- •Тип_функціі (* імя_покажчика) (специфікація_параметрів);
- •5.11 Покажчики на void
- •5.12 Арифметика покажчиків
- •10. Структури, об’єднання, перерахування
- •7.1 Структури
- •7.2 Ключове слово typedef
- •7.3 Об’єднання
- •7.4Перераховуваний тип (Enum)
- •Enum dataType
- •Enum day
- •11 Динамічне виділення пам'яті
5.3 Масиви
А тепер повернемося до масивів. Нехай є опис int a [5]; Він визначає масив розміром 5 елементів, тобто п'ять послідовних розташованих осередків пам'яті a [0], a [1], a [2], a [3], a [4]. Адреса i-го елемента масиву дорівнює сумі адреси початкового елемента масиву і зміщення цього елемента на i одиниць від початку масиву. Це досягається індексуванням: a [i] - i-й елемент масиву. Але доступ до будь-якого елементу масиву може бути виконаний і за допомогою покажчиків, причому, більш ефективно. Якщо uk-покажчик на ціле, описаний як int * uk, то uk після виконання операції uk = &a[0] -містить адресу a [0], а uk + i вказує на i-й елемент масиву. Таким чином, uk + i є адреса a [i]. Оскільки ім'я масиву в програмі ототожнюється з адресою його першого елемента, то вираз uk = & a [0] еквівалентно такому: uk = a. Тому значення a [i] можна записати як *(a+i). Застосувавши до цих двох елементів операцію взяття адреси, отримаємо, що &a[i] та a+i ідентичні.
На прикладі наведено текст програми з функцією obmen (x, y), яка міняє місцями значення двох цілих величин(рис. 5.8). Так як x, y - адреси змінних a і b, то * x і * y забезпечують непрямий доступ значенням a і b. До сказаного додамо, що використання покажчиків дозволяє нам оминати обмеження мови Сі, згідно з якими функцій може повертати лише одне значення.
Якщо як функції передається ім'я масиву, то воно фактично визначає адресу початку масиву, тобто є покажчиком. Як ілюстрацію напишемо чергову версію функції length, що обчислює довжину рядка. Якщо ім'я масиву передається функції, то в самій функції можна виходити з того, що вона працює з масивом, а можна виходити з того, що вона працює з покажчиком.
Приклад 7.Заміна місцями значення двох цілих величин.
/ * обмін a і b * /
#include <stdio.h>
void zamina (int * x, int * y){
int t;
t =* x;
* x =* y;
* y = t;
}
int main () {
int a, b;
a = 3; b = 7;
zamina (&a, & b);
printf ("a =% d b =% d", a, b);
}
Рисунок 5.8 - Заміна місцями значення двох цілих величин.
На схемі вказано як відбувається обмін між aіb. Суцільними лініями вказано я ми через код бачимо обмін, пунктиром, як відбувається обмін самих даних.
У визначенні функції формальні параметри char s [] і char * s абсолютно ідентичні.
5.4 Операція s++
(приклад 2) збільшення на одиницю поточне значення покажчика, спочатку вказує на перший символ рядка, а операція * s! = '\ 0' порівнює черговий символ ознакою кінця рядка.
Приклад 8Збільшення на одиницю поточне значення покажчика
/ * довжина рядка * /
int length (char * s) {
int i;
for (i = 0; * s! = '\ 0'; s++)
i++;
return i;}
5.5 Операції ==, !=
Крім раніше розглянутих операцій адресної арифметики, до покажчиків можна застосувати операції порівняння == і! =. Навіть операції відношення <,> = і т.п. працюють правильно, якщо покажчики посилаються на елементи одного і того ж масиву. В останньому випадку можливе навіть віднімання посилань: якщо u і s посилаються на елементи одного масиву, то us є число елементів між u і s. Використовуємо цей факт для складання ще однієї версії функції length (рис. 5.9). Спочатку u вказує на перший символ рядка (char * u = s). Потім у циклі по черзі перевіряється кожен символ, поки зрештою не буде виявлений "\ 0". Різниця us дає саме довжину рядка.
Приклад 9. Функція length
/ * довжина рядка * /
int length (char * s) {
char * u = s;
while (* u! = '\ 0')
u++;
return (u-s);
}
Рисунок 5.9 – Ілюстрація функції length
І для даного випадку u-s = 3(останній нуль-символ не рахується).