
- •1 Основні елементи мови с
- •1.1 Алфавіт мови програмування
- •1.2 Лексеми
- •1.3 Ключові слова
- •1.4 Ідентифікатори
- •1.5 Класифікація типів даних
- •1.6 Літерали
- •1.7 Оператори
- •1.8 Коментарі
- •1.9 Директиви препроцесора
- •1.10 Організація програми
- •2 Операції та вирази
- •2.1 Загальні відомості
- •2.2 Арифметичні операції
- •2.3 Операції приведення типів
- •2.4 Операції присвоєння
- •2.5 Операції інкремента і декремента
- •2.6 Операції порівняння
- •2.7 Операції зсуву
- •2.8 Порозрядні операції
- •2.9 Логічні операції
- •2.10 Операція sizeof
- •2.11 Операція послідовного обчислення
- •2.12 Операція умови (?:)
- •2.13 Адресні операції
- •3 Прості типи даних
- •3.1 Оголошення змінних
- •3.2 Час існування та область видимості змінних
- •3.3 Цілі типи даних
- •3.4 Дійсні типи даних
- •4 Оператори керування
- •4.1 Оператор розгалуження if
- •4.2 Оператор розгалуження if-else
- •4.3 Оператор множинного розгалуження switch
- •4.4 Оператор циклу for
- •4.5 Оператор циклу while
- •4.6 Оператор циклу do while
- •4.7 Оператор break
- •4.8 Оператор continue
- •5 Функції
- •5.1 Основні поняття
- •5.2 Види виклику функцій
- •5.3 Область видимості
- •5.4 Порожній тип void
- •5.5 Передача аргументів у функцію
- •5.6 Рекурсивні функції
- •5.7 Прототипи функцій
- •6 Покажчики
- •6.1 Визначення та ініціалізація покажчиків
- •6.2 Визначення покажчиків
- •6.3 Масиви
- •6.4 Операції порівняння
- •6.5 Копіювання рядка
- •6.6 Покажчики на функцію
- •6.7 Покажчики на void
- •6.8 Арифметика покажчиків
- •7 Масиви
- •7.1 Загальні поняття
- •7.2 Одновимірні масиви
- •7.3 Багатовимірні масиви
- •8 Рядки в с
- •8.1 Рядки
- •8.2.Створення рядків
- •8.3 Прототипи
- •8.3 Функції перетворення буферів
- •8.4 Функції перевірки літер
- •8.5 Операції з рядками
- •9 Структури, об’єднання, перерахування
- •9.1 Структури
- •9.2 Бітові поля
- •9.3 Ключове слово typedef
- •9.4 Об’єднання
- •9.5 Перераховуваний тип
- •10 Введення та виведення даних
- •10.1 Функція виведення printf
- •10.2Функція введення scanf
- •10.3 Введення та виведення у файл
- •11 Динамічне виділення пам'яті
6.3 Масиви
Покажчики та масиви тісно пов'язані один з одним. Якщо ptr – деякий покажчик, ptr ++ збільшує його значення і він вказує на наступний. Значення ptr використовується у виразі, а потім збільшується. Аналогічно визначаються операції ptr --, ++ ptr, -- ptr. Покажчик ptr можна складати з цілим числом i. Оператор ptr ++ = i пересуває посилання на i елементів щодо поточного значення. Ці конструкції підпорядковуються правилам адресної арифметики.
На рис. 6.6 представлено шість комірок, розміром по 4 байта. Нехай покажчик р на перший елемент масиву має адресу зміщення в пам’яті 1000 байт і вказує на записані дані, тобто 0,67. Використавши інкрементування р ++ ми переходимо до наступного елемента в масиві (і зміщуємось в пам’яті на розмір типу – 4байта). Покажчик уже вказує на 2,56 з адресою 1004.
Обмежень по переміщенню в масиві немає, тому потрібно бути обережним.
При переміщенні покажчика за межі масиву(операціями р ++ чи р --), він вказуватиме на значення типу float, де знаходитиметься якийсь випадковий набір нулів та одиниць, що використовуватимуть правила переведення з двійкової системи в десяткову з плаваючою точкою, для відображення змісту.
Рисунок 6.6 – Адресна арифметика
На рис. 6.7 представлено зміщення покажчика для інших типів : int(зміщення 4 байти), double(зміщення 8 байтів), long(зміщення 4 байти), unsigned int(зміщення 4 байти).
Нехай є опис int a [5]. Він визначає масив розміром 5 елементів, тобто п'ять послідовних розташованих комірок пам'яті a [0], a [1], a [2], a [3], a [4]. Адреса i-го елемента масиву дорівнює сумі адреси початкового елемента масиву та зміщення цього елемента на i одиниць від початку масиву. Це досягається шляхом індексації: a [i] – i-й елемент масиву. Більш ефективно доступ до будь-якого елементу масиву може бути виконаний за допомогою покажчиків. Якщо ptr покажчик на ціле, описаний як ptr*, то ptr після виконання операції ptr = &a[0] – містить адресу a [0], а ptr ++ i вказує на i-й елемент масиву. Таким чином, ptr++ i є адреса a [i]. Оскільки ім'я масиву в програмі ототожнюється з адресою його першого елемента, то вираз ptr = &a [0] еквівалентно такому: ptr = a. Тому значення a [i] можна записати як * (a+i). Застосувавши операцію взяття адреси, отримаємо що &a[i] та a+i ідентичні.
Рисунок 6.7 – Зміщення покажчика для різних типів даних
На рис. 6.8 наведено текст програми з функцією zamina (x, y), яка міняє місцями значення двох цілих величин. Так як x, y – адреси змінних a і b, то * x і * y забезпечують непрямий доступ значенням a і b. На схемі представлено суцільними лініями хід роботи програми, пунктиром – обмін даних.
Приклад 6.7. Заміна місцями значення двох цілих величин (рис. 6.8)
#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);
}
Приклад 6.8. Збільшення поточного значення покажчика на одиницю.
int length (char * s) { /* довжина рядка */
int i;
for (i = 0; * s! = '\ 0'; s + +)
i + +;
return i;}
Рисунок 6.8 – Заміна місцями значення двох цілих величин