- •1 Загальні поняття
- •1.1 Стандарт мови с
- •1.2 Алгоритм і його властивості
- •1.3 Системи числення
- •2 Засоби мови с
- •2.1 Алфавiт мови
- •2.2 Константи
- •2.3 Прості змiннi
- •2.4 Оголошення даних
- •2.5 Cтандартні функцiї
- •2.6 Операцiї
- •2.7 Вирази
- •2.8 Оператори
- •3 Структура програми, директиви препроцесору
- •4 Елементарні алгоритми
- •4.1 Лiнiйна програма
- •4.2 Розгалуження
- •4.3 Цикли
- •5 Вкладені алгоритми
- •6 Складні типи даних
- •7 Процедури
- •8 Операції над бітами
- •9 Файли
- •10 Зв’язані списки
2.5 Cтандартні функцiї
Мова С характерна наявнiстю порiвняно великої кiлькості стандартних функцiй. Це функцiї вводу-виводу, математичнi, обробки даних лiтерного типу, графiчнi, обробки помилок та інші. За рахунок їх використання вдалося розробити компактний компілятор, який не займає багато пам’яті, та зробити коротшими самі програми, бо для кожної конкретної задачі під’єднуються лише потрібні функції. Звертання до функцiї здiйснюється шляхом вказання у вiдповiдному мiсцi програми її iменi, пiсля якого в круглих дужках дається перелiк параметрiв. Кожна функцiя повертає якесь значення – результат її виконання. Для того, щоб функцiя могла бути використаною, до програми повинен бути пiд’єднаним за допомогою директиви препроцесору #include файл, де ця функцiя описана. Нижче в прикладах дається опис окремих функцiй i їх параметрiв.
Перелік та опис функцій можна переглянути за допомогою довідника, який, як правило, постачається разом з компілятором.
2.6 Операцiї
За кiлькiстю операндiв операцiї подiляються на унарнi, бiнарнi i тренарнi. Вони поданi в таблицi 2.6.
Унарний плюс (+) або мінус (-) використовуються для визначення знака числа. Якщо знак не вказаний, то за замовчуванням приймається плюс (додатнє число).
Якщо перед змінною стоїть операція тільда (~ зворотній код), то в результаті її виконання всі одиниці будуть замінені на нулі і навпаки.
Нехай, наприклад, маємо двійкове число 0000 0010 (десяткове 2), тоді ~(0000 0010)=1111 1101 (десяткове 253).
Таблиця 2.6 – Знаки операцій
|
Знак |
Найменування операції |
Знак |
Найменування операції |
|
Унарні |
|||
|
+, - |
Унарний плюс та унарний мiнус |
~ |
Зворотнiй код (тiльда) |
|
! |
Логiчне заперечення (“НЕ”) |
sizeof |
Розмiр у байтах |
|
& |
Адресацiя об’єкта |
* |
Непряма адресацiя |
|
++ |
Збiльшення на одиницю |
-- |
Зменшення на одиницю |
|
Бiнарнi |
|||
|
+, - |
Додавання, вiднiмання |
*, / |
Множення, дiлення |
|
% |
Залишок вiд дiлення |
, |
Послiдовне виконання |
|
<< |
Зсув улiво |
>> |
Зсув управо |
|
& |
Порозрядне “I” |
| |
Порозрядне включне “АБО” |
|
&& |
Логiчне “I” |
|| |
Логiчне “АБО” |
|
>, < |
Бiльше, менше |
^ |
Виключне “АБО” |
|
>= |
Бiльше або дорiвнює |
<= |
Менше або дорiвнює |
|
== |
Дорiвнює (порiвняння) |
!= |
Не дорiвнює |
|
= |
Просте присвоєння |
-= |
Присвоєння з вiднiманням |
|
+= |
Присвоєння з додаванням |
*= |
Присвоєння з множенням |
|
/= |
Присвоєння з дiленням |
%= |
Присвоєння з залишком від ділення |
|
<<= |
Присвоєння зi зсувом уліво |
>>= |
Присвоєння зi зсувом управо |
|
^= |
Присвоєння з виключним “АБО” |
|= |
Присвоєння з включним “АБО” |
|
&= |
Присвоєння з порозрядним “I” |
|
|
|
Тренарна операцiя: операнд1 ? операнд2 : операнд 3 |
|||
Вище вже говорилося про те, що мова C не оперує константами логічного типу, тобто не має значень true (так) або false (ні), натомість використовується відповідно 1 або 0 – числа типу int. Разом з тим, як видно з таблиці 2.6, мова має операції відношень та логічні операції. Тому результатом унарної операції ! (логічне заперечення) у виразах логічного типу буде саме 0 або 1. Наприклад, результатом виразу 2<3 буде 1 (тобто правда, так), а !(2<3) дорівнюватиме 0 (тобто не 1). Значенням виразу !1 так само, як !2, !3 і т.д., теж буде нуль.
Операція sizeof служить для визначення кількості байт, яку займає об’єкт. Нехай, наприклад, маємо дві змінні: int k; float s; Тоді після виконання операції k=sizeof(s); змінна k дорівнюватиме кількості байт, яку займає змінна s (k = 4).
Мова С має широкі можливості для роботи безпосередньо з адресами пам’яті, для цього служать операції: адресація (&) і непряма адресація (*) об’єкта. Прийоми роботи з ними покажемо на прикладі. Нехай маємо змінні:
float x=7.55, g, *p=&x;
Тут оголошена змінна p типу адреси, під час оголошення вона ініціаліазована адресою змінної x, тобто їй присвоєно значення адреси змінної x. Тоді після виконання оператора g = *p; (він читається так: присвоїти змінній g значення, яке знаходиться під адресою p) змінна g прийме значення 7,55. Цей приклад можна показати інакше:
float x=7.55, g, *p;
p=&x;
g=*p;
Одержимо ті ж результати.
Звернемо увагу на те, що змінна типу адреси (в останньому прикладі це змінна p) може бути тільки цілою. Описувач float означає не тип її, а крок, з яким розміщуються дані в пам’яті машини. Цим іноді користуються програмісти. Нехай, наприклад, маємо такі оголошення:
int a=23, b=46, *m=&a, n;
Тут змінній m присвоєно значення адреси змінної a. Після виконання команди n=*(m+1); змінна n прийме значення 46, тобто значення змінної b, яка знаходиться далі на один крок типу int від змінної a. Додамо, що компілятор розміщує дані в пам’яті машини в тій послідовності, в якій вони перечислені під час оголошення.
Змінні адресного типу, тобто призначені для запам’ятовування адрес, називаються вказівниками.
За допомогою операції ++ (інкремент) можна збільшувати, а -- (декремент) – зменшувати число на одиницю. Наприклад, маємо оголошення: int i=5; Тоді після виконання операції i++; значення змінної і дорівнюватиме 6, а після i--; – числу 4. Має значення місце встановленя операцій інкремент та декремент у виразах – перед змінною чи після неї. Якщо вони стоять після змінної, то спочатку ця змінна використовується, а потім нарощується. Нехай, наприклад, маємо такі вирази:
int k = 3, a, b;
a = 2*k++;
b=2*++k;
Обчислення будуть відбуватися в такій послідовності:
k=3, a = 6, k=4, k=5 , b=10.
Операція % (залишок вiд дiлення) призначена для отримання залишку від ділення двох цілих чисел. Наприклад, значення виразу 10%3 дорівнюватиме 1.
Операцію , (послідовне виконання) застосовують там, де зазвичайно знаходиться один вираз, а потрібно помістити два. Таке може статися, наприклад, у заголовку оператора циклу.
Операції << та >> дозволяють зсунути відповідно вліво або вправо двійковий код комірки пам’яті на задану кількість розрядів. Нехай, наприклад, маємо такі оператори:
int k=5, n;
n=k<<2;
Двійковий код числа 5 дорівнює 101. В комірку n воно запишеться зміщеним на два розряди вліво (в сторону старшого розряду), тобто дорівнюватиме 10 100 (під час зміщення звільнені молодші розряди заповняться нулями). Тоді в десятковій системі числення одержимо:
n = 1*24 + 0*23 + 1*22 + 0*21 + 0*20 = 16 + 0 + 4 + 0 + 0 = 20.
Зміщення вмісту комірки на один розряд вліво або вправо ідентичне відповідно множенню або діленню числа на 2. Цим часто користуються програмісти для підвищення швидкості обчислень, але, як буде показано далі в розділі про побітові операції, цей прийом на різних машинах з різними операційними системами та компіляторами слід реалізовувати по-різному.
Таблиця 2.7 – Результати обчислення логічних виразів
|
a |
b |
!a |
~a |
a && b |
a & b |
a || b |
a | b |
a ^ b |
|
1 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
|
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
|
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
|
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
Як уже вище зазначалося, результатом виконання логічних операцій мовою С є ціле число нуль або одиниця, а не логічні значення true або false, які мають інші мови програмування. Навіть ті компілятори, які відповідно до стандарту С99 мають ці логічні значення, сприймають їх, як відповідно 1 або 0. Результати виконання логічних операцій показані в таблиці 2.7.
Наведемо декілька прикладів. Значення виразу 2<3 && 5 дорівнює 1. Тут 2<3 дорівнює 1 (правда), 5 дорівнює 101 (у двійковій системі числення), воно містить аж дві одиниці, тому вважається теж правдою. Отже 1 && 1 = 1.
Операції && – логiчне “I”, та & – порозрядне “I” відрізняються між собою. Під час виконання виразів з порозрядним “I” перевіряється на співпадання кожний розряд. Наприклад, 5&&3=1. Представимо ці вирази двійковою системою числення, тоді 101&&11=1, бо обидва операнди – і лівий, і правий містять одиниці (взагалі – хоча б одну, а тут аж по дві). А результат виконання виразу 5&3=001 (101&011=001).
Подібно до цього виконуються й операції || – логічного “АБО” та | – порозрядного включного “АБО”. Наприклад, результатом виразу 5||3 буде число 1, бо обидва операнди мають по дві одиниці (а потрібно хоча б одну. Результатом виразу 5|3, тобто 101|011, буде число 111, бо в усіх трьох розрядах на відповідних місцях обох двійкових операндів міститься хоча б одна одиниця (з двох у різних числах). Операція ^ – порозрядного виключного “АБО” відрізняється від порозрядного включного “АБО” тим, що результат дорівнює нулю тоді, коли обидва операнди – одиниці. Наприклад, в результаті виконання виразу 5^3 (101^011) отримаємо 110, бо крайні праві (наймолодші) розряди обидвох операндів містять по одиниці.
Результатами операцій відношення мовою С теж будуть нулі або одиниці. Вони виконується подібно до загальноприйнятих. Слід лише особливо підкреслити, що операція порівняння мовою С на відміну від більшості інших мов програмування, має вигляд: == (два знаки =). Оскільки тип виразу мовою С не регламентується, то компілятор його не контролює, тому в тих місцях програми, де може бути логічний вираз, дозволено писати й один знак =, який тоді означає операцію присвоєння.
Операцiї з присвоєнням означають одночасно двi операцiї, наприклад, нарощення змiнної s на 2,3 можна виконати такими двома способами: s=s+2.3; або s+=2.3; На другий спосіб машина затратить менше часу, ніж на перший, бо в першому випадку адреса змінної s буде згенерована двічі: перед її викликом на суматор і під час запису назад в оперативну пам’ять після зміни, а в другому – лише один раз.
Тренарна операцiя виконується так: якщо значення операнд1 = 0, то результат = операнд3, iнакше – операнд2. Наприклад, значенням виразу 2<3?7:18 буде число 7, виразу 3?7:18 – теж число 7, виразу 1?2:3 – число 2, а виразу 0?2:3 – число 3.
Тренарні операції можуть бути вкладеними. Наприклад, якщо відомо значення змінної den – порядковий день місяця, то порядковий номер декади (десятиденки) можна знайти з такого виразу:
den<11?1:den<21?2:3.
