- •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.2 Визначення покажчиків:
Приклад 3.Синтаксис покажчика.
int* p=&a; /* покажчик р містить значення адреси змінної а */
float* ptr (NULL); /* Нульовий покажчик на об’єкт типу float */
char* p; /* Неініціалізований покажчик на об’єкт типу char */
Значення адреси змінної одержується за допомогою унарної операції ”&”.Розглянемо код з виводом в консольне вікно:
Приклад 4.Використання операції ”&”.
#include <iostream>
#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;
}
Результат роботі:
Рисунок 5.4 - Схема даних в памяті:
Як бачимо в зміній а зберігається значення 8, в зміній р зберігається значення адреси а, тобто р вказує на комірку зі зміною а.
Якщо ж операція «*» використовується не при ініціалізації покажчика то ця операція має назву розіменовування:
Приклад 5. Розіменовування покажчика(рис. 5.5).
int x=2; /*змінна типу int */
int *y =&x; /* покажчик на елемент даних типу int */
int z =*y; /* через покажчик до поля x вноситься значення 1,тобто z=1 */
Рисунок 5.5 - Розіменовування покажчика
Zзвертається доy,yце покажчик наx, що містить адресу. Присвоїтиzзначенняyми не можемо, тому що це різні типи даних: адреса і значення. Шляхом розіменовування ми отримуємо значення на яке вказуєyі присвоюємо його зміннійz.
Власне унарна операція «*» застосована до покажчика, забезпечує доступ до вмісту комірки пам'яті, на яку посилається покажчик. Наприклад, * yможна описати словами як "те, що міститься за адресою, на який вказуєy".
Покажчики можуть використовуватися в виразах. Якщо. наприклад, зміна uk вказує на ціле x, то * y може у всіх випадках використовуватися замість x; так, * y+1 збільшує x на одиницю, а *y= 0 рівносильне x = 0. Два оператори присвоюванняy= &x;z=*y; виконують те ж саме, що і один операторz= x. Користь від застосування покажчиків в таких ситуаціях, м'яко висловлюючись, невелика.
Найбільш повні їх переваги при обробці масивів і, зокрема, символьних рядків. Покажчики та масиви тісно пов'язані один з одним. Перш ніж розглянути цей зв'язок детально, зазначимо, що якщо uk - деякий покажчик, то uk ++ збільшує його значення і він тепер вказує на наступний, сусідню адресу об'єкта. Значення uk використовується у виразі, а потім збільшується. Аналогічно визначаються операції uk--, + + uk,--uk. У загальному випадку покажчик uk можна складати з цілим числом i. Оператор uk + = i пересуває посилання на i елементів щодо поточного значення. Ці конструкції підпорядковуються правилам адресної арифметики.
Рисунок 5.6 - Адресна арифметика
Як бачимо є шість елементів – шість комірок, розміром по 4 байта(рис. 5.6). Для першого елемента масиву (що за одне й є покажчиком на масив) наприклад взято зміщення в памяті 1000 байт, там де нам було виділено її ОС в ОЗП. До речі , покажчик вказує й на тип, таким чином зміщення буде на відповідний розмір типу(в даному випадку для float – 4байта) і вказувати на дані що містяться в наступних 4-х байтах.
Таким чином, нехай покажчик (p) на перший елемент масиву (що за одне й є покажчиком на масив) має адресу (зміщення) 1000 і вказує на записані там дані , тобто 0,67. Використавши інкрементування р++ ми переходимо до наступного елемента в масиві (і зміщуємось в памяті на розмір типу – 4байта). Покажчик уже вказує на 2,56 з адресою 1004.
Обмежень по переміщенню в масиві немає, тому потрібно бути обережним.
Наприклад: у нас є 6 елементів в масиві, але це не означає, що покажчик не може виходити за його межі, він може вказувати на комірки з адресою 1024, 1028 і т.д. Отже, якщо ми перемістимо покажчик за межі масиву(операціями р++ чи р--), то він вказуватиме на значення типу float і що там буде за значення не відомо, так як там знаходитиметься «сміття», якийсь випадковий набір нулів та одиниць, що використовуватимуть правила переведення з двійкової системи в десяткову з плаваючою точкою, щоб відобразити зміст.
Для інших типів все ж так саме: int(зміщення 4 байти), double(зміщення 8 байти),long(зміщення 4 байти),unsignedint(зміщення 4 байти),byte(зміщення 1 байт) і т.д.. (рис. 5.7)
Рисунок 5.7 – Зміщення покажчика для різних типів даних.