
- •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 Покажчики
6.1 Визначення та ініціалізація покажчиків
Типова ЕОМ має масив послідовно нумерованих або адресованих комірок (секцій) пам'яті, якими можна маніпулювати окремо або прилеглими групами. Кожна з яких має мінімальний розмір один байт. Комірки нумеруються послідовно.
Рисунок 6.1 – Послідовна нумерація комірок пам’яті
На рисунку 5.1 адреси комірок зображуються у вигляді двокрапки та номера комірки . Наприклад , «:1979».
Покажчик – це група комірок (часто дві або чотири), що можуть зберігати адресу.
Синтаксис визначення покажчика наступний:
<тип> *<ім’я покажчика>
де тип – це тип даних на який вказує покажчик;
ім’я покажчика – ідентифікатор.
Приклад 6.1. Присвоєння адреси змінній (рис. 6.2)
int a; /* змінна типу int */
p = 13; /* присвоєння змінній значення */
int * p; /* p є покажчиком на int */
p = &a; /* операція взяття адреси присвоєння
адреси a змінній p */
Приклад 6.2. Змінна та її адреса (рис. 6.3)
а = 13; /* присвоєння змінній значення */
varsecond = а; /* запис значення а в змінну varsecond */
p = &a; /* операція присвоєння адреси a змінній p */
Покажчик визначається наступним чином:
<тип> *< ідентифікатор> = <ініціалізатор>;
Під ініціалізатором розуміється якась адреса змінної (тоді необхідно використати взяття адреси змінної &) або вже існуючий покажчик.
а)
б)
а) Представлення змінної
б) Детальна схема присвоєння адреси змінній
Рисунок 6.2
Рисунок 6.3 – Змінна та її адреса
6.2 Визначення покажчиків
Приклад 6.3. Синтаксис покажчика
int* p = &a; /* покажчик р містить значення адреси
змінної а */
float* ptr (NULL); /* нульовий покажчик на об’єкт типу
float */
char* p; /* неініціалізований покажчик на
об’єкт типу char */
Значення адреси змінної одержується за допомогою унарної операції ”&”. Розглянемо код з виводом в консольне вікно:
Приклад 6.4. Використання операції ”&” (рис. 6.4)
#include <stdlib.h>
int main()
{
int a = 8;
int * p = &a;
printf(" p=%i, &p=%i, a=%i, &a=%i \n", p, &p, a, &a);
system("PAUSE");
return EXIT_SUCCESS;
}
Результат роботи програми:
Рисунок 6.4 – Схема даних в памяті
В змінній а зберігається значення 8, в покажчику р зберігається значення адреси а, тобто р вказує на комірку з індифікатором а.
Якщо ж операція «*» використовується не при ініціалізації покажчика то ця операція має назву розіменовування:
Приклад 6.5. Розіменовування покажчика (рис.6.5)
int x=1; /* змінна типу int */
int * y =&x; /* покажчик на елемент даних типу int */
int z =* y; /* через покажчик до поля x вноситься
значення 1 */
Рисунок 6.5 – Розіменовування покажчика
Нехай y – це покажчик на x, що містить адресу. Присвоїти значення z змінній y ми не можемо, тому що це різні типи даних: адреса і значення. Шляхом розіменовування отримуємо значення на яке вказує y і присвоюємо його змінній z.
Унарна операція «*» застосована до покажчика, забезпечує доступ до вмісту комірки пам'яті, на яку посилається покажчик. Наприклад, * y можна описати словами як "те, що міститься за адресою, на який вказує y".
Покажчики можуть використовуватися у виразах. Якщо, покажчик y вказує на ціле x, то * y може у всіх випадках використовуватися замість x; так, * y+1 збільшує x на одиницю, а * y=0 рівносильне x=0. Два оператори присвоювання y = &x; z = * y; виконують те ж саме, що і один оператор z = x. Користь від застосування покажчиків в таких ситуаціях невелика.