
- •Вказівники на функції. Масиви вказівників на функції. Приклади.
- •В казівники на функції. Функції як параметри функцій. Приклади.
- •Функції з довільним числом параметрів. Приклади.
- •Обробка символів та масивів символів. Бібліотечні функції обробки символів.
- •Рядки. Подання рядків у пам’яті. Ініціалізація. Рядкові літерали.
- •Структури. Оголошення та ініціалізація. Розміщення у пам’яті. Приклади.
- •Структури. Вкладені структури. Доступ до полів структур, вкладених структур. Приклади.
- •Структури. Вказівники на структури. Динамічні структури. Приклади.
- •Структури з бітовими полями. Оголошення та ініціалізація. Обробка.
- •Структури як параметри та результати функцій.
- •Масиви структур. Оголошення, ініціалізація. Обробка.
- •Об’єднання. Розміщення у пам’яті. Ініціалізація. Обробка.
Структури. Вказівники на структури. Динамічні структури. Приклади.
Вказівники на структури.
Оскільки ім'я структурного типу володіє всіма правами імен типів, те дозволено визначати покажчики на структури: імя_структурного_тіпа * імя_указателя_на_структуру; Якщо функції передається велика структура, те, чим копіювати її цілком, ефективніше передати вказівник на неї. Покажчики на структури нічим не відрізняються від покажчиків на звичайні змінні. Оголошення time * pt; повідомляє, що pt - це покажчик на структуру типу struct time. Якщо pt вказує на структуру time, то * pt - це сама структура, а (* pt). Hour і (* pt). Minutes - її елементи. Використовуючи покажчик pt, ми могли б написати time origin, * pt; pt = &origin; printf ("origin: (% d,% d) \ n", (* pt). hour, (* pt). minutes); Дужки в (* pt). Hour необхідні, оскільки пріоритет операції «." Вище, ніж пріоритет операції разименованія «*». Вираз * pt.hour буде проінтерпретувати як * (pt.hour), що невірно, оскільки pt.hour не є покажчиком. Покажчики на структури використовуються дуже часто, тому для доступу до її елементів була придумана операція «звернення до елементу структури за вказівником», скорочено «стрілка» з формою запису «->». Якщо t - покажчик на структуру, то t-> елемент-структури є її окремий елемент. Тому printf можна переписати у вигляді printf ("origin: (% d,% d) \ n", pt-> hour, pt-> minutes); Операції. і -> левоассоціатівни, тобто виконуються зліва направо. Таким чином, при наявності оголошення chronos ch, * cht = &ch; наступні чотири вираження будуть еквівалентні: ch.begin.hour cht-> begin.hour (Ch.begin). Hour (Cht -> begin). Hour Операції доступу до елементів структури. і -> разом з операторами виклику функції () та індексації масиву [] займають найвище положення в ієрархії пріоритетів та виконуються раніше будь-яких інших операторів. Наприклад, якщо задано оголошення struct { int len; char * str; } * P; то + + P-> len збільшить на 1 значення елемента структури len, а не покажчик p, оскільки в цьому виразі як би неявно присутні дужки: + + (p-> len). Щоб змінити порядок виконання операцій, потрібні явні дужки. Так, у (+ + р) -> len, перш ніж узяти значення len, програма збільшить покажчик p. В (р ++)-> len покажчик p збільшиться після того, як буде взято значення len (в останньому випадку дужки не обов'язкові). За тими ж правилами * p-> str позначає вміст об'єкта, на який вказує str; * p-> str + + збільшить покажчик str після отримання значення об'єкта, на який він вказував (як і в вираженні * s + +), (* p-> str ) + + збільшить значення об'єкта, на який вказує str; * p + + -> str збільшить p після отримання того, на що вказує str. Часто виникає проблема, при оголошенні структури оголосити там покажчик на цю ж структуру. Не дивлячись на те, що опис структури ще не завершено, формат мови це дозволяє. Наприклад, опишемо структуру List, що представляє собою односпрямований список, де в якості даних опишемо змінну типу int. struct List { int dat; List * next; }; Якщо структури містяться один в одному, то використовують предоб'явленіе структури. Наприклад struct B; struct A {B b;}; struct B {A a;}; Розглянемо приклад програми створює такий список і виводить його вміст на консоль. # Include <stdio.h> struct List { int dat; List * next; }; void main () { int i; List * p, * heap = new List; for (p = heap, i = 0; i <10; i + +) { p-> dat = i; p = p-> next = new List; } for (p = heap, i = 0; i <10; i + +) { printf ("% d", p-> dat); p = p-> next; } } Тут ми описали два покажчики: heap - для вказівки початку списку, p - для пересування за списком; і просту змінну, як лічильник циклу. На відміну від масиву, наш список буде "розкиданий" по пам'яті, оскільки оператор new виділяє перші вільні блоки пам'яті, але це неважливо, оскільки ми пересуваємося за списком, використовуючи збережені в самому списку адреси: p = p-> next;.
Динамічні структури