Тема 5 Типи даних, оператори та вирази в С

Лекція 17

Алфавіт, лексеми, синтаксис мови

У природній мові спілкуванння виділяють чотири основні елементи: символ, слово, словосполучення та речення. Подібні елементи існують і в алгоритмічній мові, тільки слова мають назву лексеми, словосполучення — вирази, а речення — оператори. Лексеми створюються із символів, вирази — із лексем та символів, оператори — з символів, виразів і лексем.

Алфавіт мови C включає:

·         великі (A−Z) і малі (a—z) літери латинського алфавіту та символ підкреслення ( _ );

·         арабські цифри від 0 до 9;

·         знаки арифметичних дій +, −, *, /, %, ++, —;

·         знаки побітових операцій <<, >>, &, |, ~, ^;

·         знаки відношень <, <=, ==, !=, >, >=;

·         знаки логічних операцій &&, ||, !;

·         розділові знаки , ; : пропуск;

·         спеціальні знаки ., =, −>, ?, \, $, #, ‘, “;

·         символи дужок (, ), [, ], {, }.

Інші символи, а також літери кирилиці не використовуються для побудови базових елементів мови або для їх розділу, але вони можуть застосовуватись у символьних константах та коментарях.

Лексеми, тобто базові елементи мови з певним самостійним значенням, складаються із символів алфавіту. До них відносять ідентифікатори, ключові слова, знаки операцій, константи, роздільники (дужки, крапка, кома, символи пропуску). Межі лексем визначаються іншими лексемами−роздільниками або знаками операцій.

Ідентифікатором, тобто ім’ям програмного об’єкта, називається будь−яка послідовність літер латинського алфавіту, цифр i символу підкреслення за умови, що першою стоїть літера або символ підкреслення, а не цифра.

Існує два різновиди ідентифікаторів:

·         стандартні, наприклад, імена всіх вбудованих у мову функцій;

·         користувальницькі.

Характерно, що мова C чуттєва до регистру літер, тому компілятор розпізнає великі і малі літери латинського алфавіту як різні символи. Це дає можливість створювати ідентифікатори, що однаково читаються, але відрізняються написом одного або декількох символів. Наприклад, ідентифікатори «Sigma», «sigma» і «sigMa» вважаються різними.

Ідентифікатори можуть мати будь−яку довжину, але значимими є не більше 31 символу від початку ідентифікатора, a в деяких компіляторах це обмеження ще більш суворе (не бiльше 8 символів). Імена програмних об’єктів створюються на етапі оголошення даних, після цього їх можна використовувати в різних операторах програми. При виборі ідентифікатора необхідно керуватись наступними правилами:

·         рекомендується не шкодувати часу на створення ідентифікаторів переважно за їх змістовим призначенням;

·         ім’я програмного об’єкта повинно легко розпізнаватись і, бажано, не мати символів, які можна переплутати між собою;

·         ідентифікатор не повинен збігатися з ключовими словами, а також з іменами стандартних об’єктів мови C++;

·         не слід починати ідентифікатори із символу підкреслення, бо вони можуть співпадати з іменами системних функцій або змінних;

·         для розділу частин імені можна використовувати символ підкреслення;

·         всередині ідентифікатора не можна розміщати символи пропуску.

Ключовими (службовими) словами називають ряд зарезервованих ідентифікаторів, що вживаються для побудови конструкцій мови і мають фіксоване значення. За смисловим навантаженням службові слова поділяються на такі основні групи:

·         специфікатори типівchar, int, long, typedef, short, float, double, enum, struct, union, signed, unsigned, void;

·         квалифікатори типівconst і volatile;

·         класи памятіauto, extern, register, static;

·         для побудови операторівfor, while, do, if, else, switch, case, continue, goto, break, return, default, sizeof.

У таблиці 3 наведено список основних ключових слів C

Таблиця 3 − Ключові слова C

asm

delete

goto

register

throw

auto

do

if

return

try

break

double

inline

short

typedef

case

else

int

signed

typename

catch

enum

long

sizeof

union

char

explicit

new

static

unsigned

class

extern

operator

struct

virtual

const

float

private

switch

void

continue

for

protected

template

volatile

default

friend

public

this

while

 

Як роздільники лексем застосовуються такі символи: пропуск, табуляція, символ нового рядка, коментар. Між будь−якими двома лексемами допускається довільна кількість символів−роздільників. Крім того, деякі лексеми («*», «+», «,», « », «(», «−>» тощо) самі є роздільниками і відділяти їх від інших лексем символами−роздільниками необов’язково.

 

Структура програми

Основними частинами типової структури програми на С++ є такі:

·         директиви препроцесорної обробки;

·         опис зовнішніх змінних (вихідних даних і результатів) та функцій;

·         функції програми;

·         головна функція — програми main(), що має вигляд:

main()

{

опис змінних; виконавчі оператори;

}

У загальному випадку програма складається з декількох функцій, що не перетинаються (тобто «вкладення» однієї функції в іншу неприпустиме). Перед функціями і між ними можуть бути присутні оголошення об’єктів даних і оператори препроцесорної обробки. Функції користувача, які викликаються у головній функції main(), слід обов’язково описати до їх використання. Наведемо приклад запису фрагмента простої програми:

//..............фрагмент простої програми на С

#include <iostream.h>

#include <соnio.h> //директиви препроцессора

const int n=20;

void main()

{

float mas[n]; //опис одномірного масиву

//....................ввід елементів масиву

for (int i=0; i < n; i++)

  cin >> mas[i];

//........... виконання перетворень

//.......вивід перетвореного масиву

for(int i=0; i < n; i++)

  cout << " " << mas[i] << " ";

  getch (); // затримка результату на екрані

}

Коментарі необхідні для пояснень призначення тих чи інших частин програми і їх текст завжди ігнорується компілятором. Мова С++ використовує два різновиди коментарів:

·         // текст — однорядковий коментар, який починається з двох символів «/» («коса риска») і закінчується символом переходу на новий рядок;

·         /* текст */багаторядковий коментар, що розташовується між символами−дужками «/*» і «*/».

Багаторядкові коментарі не можуть бути вкладеними один в одний, а однорядкові коментарі можна вкладати в багаторядкові коментарі. Багаторядкові коментарі доцільно застосовувати для тимчасового виключення блоків при налагодженні програми.

Наведемо кілька порад стосовно раціонального складання коментарів:

·         коментарі повинні бути добре складеними реченнями, мати правильну пунктуацію та містити тільки потрібну для супроводу інформацію;

·         пропуск — один з найбільш ефективних коментарів, що значно поліпшує розуміння програми;

·         штрихові лінії коментаря або порожні рядки застосовуються для поділу функцій та інших логічно завершених фрагментів програм.

 Директива препроцесора #include<iostream.h> забезпечує підключення до програми засобів зв’язку зі стандартними потоками введення−виведення даних. Ці засоби знаходяться у заголовному файлі iostream.h, де і (input) — введення, о (output) виведення, stream — поток, h (head) — заголовок. Ураховуючи те, що середовище Borland C не забезпечує затримку результатів на екрані, у текстах програм посібника з цією метою використано стандартний потік введення сіn (бібліотека iostream.h), функцію введення getch() (бібліотека conio.h) тощо.

При створенні програми враховують такі основні вимоги:

·         усі використані константи, змінні, функції та нестандартні типи повинні бути оголошеними (описаними) до їхнього першого використання, і ці оголошення можна розміщати в будь−якому місці програми;

·         кожний оператор мови закінчується символом «;»;

·         фігурні дужки (« { » та « } ») виділяють складений оператор і все, що подано між такими дужками, синтаксично сприймається як один оператор;

·         вкладені блоки повинні мати відступ у 3−4 символи, при цьому блоки одного рівня вкладеності слід вирівняти за вертикаллю.

 

Дані та операці

Типи даних

Обробка даних різного типу є головною метою будь−якої програми. Кожне з даних характеризується класом пам’яті, ім’ям, типом і значенням. Імена дозволяють ідентифікувати дані, тобто відрізняти їх між собою. Програміст обирає тип кожної величини, що використовується для подання реальних об’єктів. Тип задає множину можливих значень даних і способи їх зберігання, перетворення та використання.

Обов’язкове оголошення типу даних дозволяє компілятору робити перевірку допустимості різних конструкцій програми.

Усі типи даних мови C можна розділити на основні (базові) і складені. Основні типи визначені для представлення цілих, дійсних, символьних і логічних даних. На основі цих типів вводиться опис складених типів, до яких належать масиви, перелічення, функції, структури, посилання, покажчики, об’єднання і класи.

Основні типи даних (таблиця 4) часто називають арифметичними, тому що їх можна використовувати в арифметичних операціях. Для опису основних типів мови C використовують такі службові слова:

·         int (цілий);

·         char (символьний);

·         bool (логічний);

·         float (дійсний);

·         double (дійсний з подвійною точністю);

·         void (порожній, не має значення).

Типи int, char, bool називають цілими, а типи float та double дійсними з плаваючою крапкою. Код, що формує компілятор для обробки цілих величин, відрізняється від коду для величин з плаваючою крапкою.

Для уточнення внутрішнього подання та діапазону значень стандартних типів мова C використовує чотири специфікатори типу:

·         short (короткий);

·         long (довгий);

·         signed (знаковий);

·         unsigned (беззнаковий).

Таблиця  4 − Базові типи даних для ПК (платформа Intel)

Тип

Розмір, байт

Значення

bool

1

true або false

unsigned short int

2

від 0 до 65 535

short int

2

від −32 768 до 32 767

unsigned long int

4

від 0 до 4 294 967 295

long int

4

від −2 147 483 648 до 2 147 483 647

int (16 розрядів)

2

від −32 768 до 32 767

int (32 розряди)

4

від −2 147 483 648 до 2 147 483 647

unsigned int (16 розрядів)

2

від 0 до 65 535

unsigned int (32 розряди)

4

від 0 до 4 294 967 295

char

1

від 0 до 256

float

4

від 1.2е−38 до 3.4е38

double

8

від 2.2е−308 до 1.8е308

long double

10

від 3.4е−4932 до 3.4е+4932

У таблиці 4 наведено діапазони значень та розміри основних типів даних (для 16−розрядного і 32−розрядного процесорів). Розмір однакового типу даних може відрізнятися на комп’юте­рах різних платформ, а також може залежати від застосованої операційної системи. Тому при оголошенні тієї чи іншої змінної потрібно чітко уявляти, скільки байт вона буде займати в пам’яті ЕОМ, щоб запобігти проблемам, пов’язаним з переповнен­ням і неправильною інтерпретацією даних. Діапазони кожного з типів (див. табл. 4) повинні бути перевірені для конкретного комп’ютера.

Змінні

Кожна програма потребує виконання різноманітних обчислень, для здійснення яких використовуються вирази, що складаються з операндів, знаків операцій і дужок. Операнди задають дані для обчислень, а операції задають дії, які необ­хiдно виконати над цими даними. Операнд є, у свою чергу, виразом, що в окремому випадку може бути константою або змінною.

Змінна — це іменована область пам’яті, у якій зберігаються дані визначеного типу. Змінна має ім’я, розмір та інші атрибути, такі як видимість, час існування тощо. Ім’я змінної служить для звертання до області пам’яті, у якій зберігається її значення. Перед використанням будь−яка змінна повинна бути описана, при цьому для неї резервується деяка область пам’яті, розмір якої залежить від конкретного типу змінної. Під час виконання програми змінна може приймати рiзнi значення.

Наведемо загальний вигляд опису змінних:

[клас пам’яті] [const] тип ім’я [ініціювання];

де необов’язковий клас пам’яті може приймати одне зі значень — auto, extern, static чи register (при описі синтаксису об’єктів програмування необов’язкові частини синтаксичних конструкцій мови подано у квадратних дужках «[]»);

модифікатор const вказує, що змінна не може змінювати своє значення, у цьому випадку її називають типізованою (іменованою) константою або просто константою;

ініціювання — це присвоювання змінній при описі початкового значення, яке записується зі знаком рівності — = значення або в круглих дужках — (значення). Зазначимо, що константа повинна бути ініційована при описі. Один оператор може містити опис декількох змінних одного типу, розділяючи їх кома­ми, наприклад:

const int n = 20, m = 5, k = 4; — ініціювання констант n, m, k цілого типу;

float h = 17.5, d(5.5), sum; — опис дійсних змінних h, d, sum, ініціювання h і d;

char sf = 'f', st[ ] = "Мудрість лишь в істині."; — ініціювання символьних змінних.

Якщо тип значення, що ініціюється, не збігається з типом змінної, то виконуються перетворення типу. Кожна змінна повинна мати своє ім’я, причому в одному блоці не може бути двох змінних з однаковим ім’ям.

Областю дії ідентифікатора змінної є частина програми, в якій його можна використовувати для доступу до зв’язаної з ним області пам’яті. Залежно від області дії змінна може бути локальною або глобальною.

Локальна змінна визначена всередині блока (нагадаємо, що блок розташований між фігурними дужками). Область її дії обмежена початком опису змінної та кінцем блока, включаючи усі вкладені блоки. Змінна, визначена поза будь−яким блоком, називається глобальною, і областю її дії вважається файл, у якому вона визначена від початку опису до його кінця.

Опис змінної може виконуватися у формі оголошення або визначення. Оголошення інформує компілятор про тип змінної і класи пам’яті, а визначення містить, крім цього, вказівку компілятору про виділення пам’яті відповідно до типу змінної. У C більшість оголошень є одночасно і визначеннями. Змінна може бути оголошена багаторазово, а визначена тільки в одному місці програми, оскільки оголошення тільки описує властивості змінної, а визначення зв’язує її з конкретною областю пам’яті.

Розглянемо далі основні типи змінних.

Цілі змінні (типу int, long, short) необхідні для збереження цілих значень і можуть бути знаковими і беззнаковими. Знакові змінні застосовують для подання як додатних, так і від’ємних чисел, при цьому один біт (найстарший) виділяється під знак. Для оголошення беззнакової змінної, тобто змінної, що приймає тільки додатні значення, необхідно використовувати ключове слово unsigned. За замовчуванням будь−який цілий тип вважається знаковим, і тому немає потреби у використанні ключового слова signed.

Символьний тип даних char застосовується у випадку, коли змінна містить інформацію про код ASCII або для побудови таких більш складних конструкцій, як рядки, символьні масиви тощо. Дані типу char також можуть бути знаковими і беззнаковими.

Змінна типу bool займає 1 байт і використовується, насамперед, у логічних операціях, тому що може приймати значення 0 (false — «неправда») або відмінне від нуля (true — «істина»). У випадку перетворення до цілого типу true має значення 1.

Стандарт C визначає три типи даних для збереження дійсних значень змінних: float, double та long double (типи з плаваючою крапкою). Тип float, як правило, використовують для збереження не дуже великих дробових чисел.

Змінна типу void не має значення, оскільки множина значень цього типу порожня. Такі змінні необхідні для узгодження синтаксису. Тип void використовується для визначення функцій, що не повертають значення, для вказівки порожнього списку аргументів функції, а також як базовий тип для покажчиків i в операції приведення типів. Наприклад, якщо немає потреби у використанні поверненого значення функції, перед ім’ям функції ставиться тип void: