Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Зубенко, Омельчук - Програмування. Поглиблений курс

.pdf
Скачиваний:
49
Добавлен:
07.03.2016
Размер:
4.72 Mб
Скачать

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

Символьний базовий тип складають звичайні й широкі символьні константи. Коди широких символів складають тип wchar_t, який визна- чено у заголовному файлі stddef.h. Прототипи функцій для виділення різних груп широких символів та їхні відображення розташовані в заго- ловному файлі wctype.h, прототипи решти символьних функцій і функ- цій для обробки рядків широких символів у файлі wchar.h.

Тип void має порожню множину значень. Він використовується: 1) у поданні типу функції, якщо вона не повертає значень; 2) для фо- рмування безтипового покажчика void*; 3) для опису порожнього списку параметрів функції. Наприклад, головна функція void main (void){} не повертає значення й не має параметрів.

3.2.3. СТАНДАРТНІ ТИПИ

До стандартних типів даних належать сукупності значень числових змінних різних розмірів. Такі змінні мають рівень доступу 3, тобто повний. Стандартні типи розподіляються на цілі, дійсні, символьні, комплексні й булевий. Вважається, що всі вони містять беззмістовне значення #, яке не має своєї ідеограми в мові С і якого набуває вираз у позаштатних (аварійних) ситуаціях 28.

Цілі типи. Діапазон конкретного цілого типу визначається специ- фікатором типу й реалізацією і для різних процесорів і компіляторів може бути різним. При моделюванні цілої арифметики цілими ма- шинними типами слід ураховувати обмеженість (скінченність) моде- лей. Це зумовлює такі їхні особливості, як переповнення при вико- нанні операцій і беззмістовність у моделі тих цілих чисел, що розта- шовані за межами машинного типу:

<cпецифікатор-цілого-типу>>::=[<модифікатор-знака>][<розмір>]\ \[<тип>]|_Bool

<тип>::=char| int <розмір>::=short |long |long long

<модифікатор-знака>::=signed | unsigned

Основою всіх цілих типів є тип int. Розмір об'єкта типу int зазви- чай збігається з розміром машинного слова в конкретному середови- щі програмування. У більшості випадків у 16-розрядному середовищі (DOS чи Windows 4.1) int займає 16 бітів, а у 32-розрядному

(Windows 95/98/NT/2000) – 32 біти. Зазначимо, що стандарт C обу-

28 Тут # є метасимволом.

301

ПРОГРАМУВАННЯ

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

Розмір типу char – 1 байт. Даний тип використовується для подан- ня кодів символів набору ASCII.

Обидва типи можуть бути модифіковані за знаком і розміром. За знаком вони розподіляються на знакові (з модифікатором signed) і беззнакові (з модифікатором unsigned). У беззнаковому варіанті ста- рший знаковий біт використовується як числовий. Тому діапазон без- знакового типу вдвічі ширший, ніж такий самий знаковий. Якщо мо- дифікатор знака відсутній, то змінна знакова. За розміром цілі по- діляються на короткі (short), довгі (long) і довгі-довгі (long long). Роз- міри типів залежать від компілятора, їх можна знайти за допомогою операції sizeof. Наприклад, sizeof(long)=4, sizeof(short)=2 тощо.

Дана операція дозволяє також отримати розмір об'єкта, заданого ви- разом sizeof(15l)=4, sizeof(‘b')=1 тощо. Стандартні розміри типів наведені в табл. 3.7.

У заголовному файлі <limits.h> визначаються розміри граничних констант для цілочислових типів компілятора. У табл. 3.8 наведені деякі з них.

Таблиця 3.7. Розмір цілих типів

 

Типовий

 

Тип

розмір

Мінімальний діапазон значень

сhar

у бітах

 

8

Від -127 до 127

unsigned char

8

Від 0 до 255

signed char

8

Від -127 до 127

int

16 чи 32

Від -32767 до 32767

unsigned int

16 чи 32

Від 0 до 65535

signed int

16 чи 32

Те саме, що int

short int

16

Від -32767 до 32767

unsigned short int

16

Від 0 до 65535

signed short int

16

Те саме, що short int

long int

32

Від -2 147 483 647 до 2 147 483 647

long long int

64

Від -(263-1) до (263-1), доданий стан-

signed long int

 

дартом C99

32

Те саме, що long int

unsigned long int

32

Від 0 до 4 294 967 295

unsigned long long int

64

Від 0 до (264-1), доданий у C99

float

32

Від 1E-37 до 1E+37, з точністю не

double

 

менше 6 значущих десяткових цифр

64

Від 1E-37 до 1E+37, з точністю не

 

 

менше 10 значущих десяткових цифр

302

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

Таблиця 3.8. Граничні цілі константи з файла limits.h

Константа

Значення (у бітах)

Визначення

СHAR_BIT

8

Розмір поля для char

UCHAR_MAX

255

Максимальне значення в char

INT_MAX

+32767

Максимальне значення в int

INT_MIN

-32768

Мінімальне значення в int

LONG_MAX

+2147483647

Максимальне значення в long

UINT_MAX

65535

Максимальне значення в un-

 

 

signed int

УС99 передбачені додаткові розширені цілі типи (extended integer type), доступ до яких здійснюється через заголовні файли stdint.h та inttypes.h. На ці типи поширюється вся ціла арифметика й правила перетворення типів.

УС99 введено також цілий булевий тип _Bool зі значеннями 0 та

1.При перетвореннях усіх цілих типів до _Bool ненульові значення перетворюються до 1, а нульові до 0.

Операції на цілих типах це звуження на них арифметичних операцій над цілими числами. Якщо ж результат певної операції ви- ходить за межі типу, то виникає ситуація переповнення. Переповнен- ня порушує основні арифметичні закони (асоціативність, дистрибу- тивність). В обчисленнях, коли переповнення відсутнє, машинна арифметика є точною моделлю звичайної цілої арифметики.

Розпочнемо з унарних цілих префіксних операцій:

<унарна-ціла-префіксна-операція>::=<унарний-мінус>| |<унарний-плюс>|<заперечення>| |<побітове-заперечення>

|<префіксне-збільшення>| |<префіксне-зменшення>

Операція унарний мінус (–) змінює знак виразу на протилежний. Це скорочений варіант віднімання: e = 0 e . Операція унарний плюс ( + ) тотожна: +e = 0 + e . Операція заперечення ! для довільного цілого

виразу e дає результат !e = (e = 0 1|0). Операція побітового запе-

речення ~ інвертує біти в цілому об'єкті. При цьому знаковий біт не зачіпається. Операція префіксного збільшення + + (зменшення -- )

додає (віднімає) 1 до (від) поточного значення цілого l -виразу. Ці опе- рації, як і постфіксні їхні варіанти, мають побічний ефект нові зна- чення записуються у l -вираз.

Приклад 3.21. Нехай int n=5; unsigned char c='0';

303

ПРОГРАМУВАННЯ

Вираз

Значення

Коментар

!n

0

 

!-5

!(-5)=0

'0'=48

~c

~0011 0000=1100 1111=207

++n

6

 

--n

4

 

Приклад 3.22. Надрукувати значення масиву int s[100] зі 100 ці- лих чисел можна таким чином:

for(int i=0; i<100; i++) printf("\ns[%d]=%d",i,s[i]);

Бінарні цілі операції це операції з цілими операндами, що від- повідають рядкам 3-15 табл. 3.5.

Вираз x % y дає залишок від ділення x на y. Якщо x ділиться на y наці- ло, то результат – 0. Наприклад, рік є високосним, якщо він ділиться на 4, але не ділиться на 100, або якщо ділиться на 400. Це можна записати так:

if(((year % 4==0) && (year % 100 !=0)) || (year % 400==0))

else

printf("Рік

%d

високосний", year);

printf("Рік

%d

невисокосний", year);

Якщо обидва операнди % невід'ємні, то й результат невід'ємний і мен- ший за дільник. Яким буде знак результату операції % із від'ємними опе- рандами, залежить від процесора, при цьому гарантується лише, що аб- солютне значення залишку менше, ніж абсолютне значення дільника.

Операції зсуву << (ліворуч) та >> (праворуч). Перший операнд ви- значає число, що зсувається, другий кількість бітів, на яку відбува- ється зсув. Тип результату це тип першого операнда. При зсуві ліво- руч зайві старші біти відкидаються, а нові молодші заповнюються 0 . При зсуві праворуч молодші біти відкидаються, значення звільнених старших бітів залежить від типу першого операнда й реалізації. Однак якщо даний тип беззнаковий або значення додатне, то ці біти будуть 0 . Якщо значення другого операнда від'ємне або більше ніж довжина в бітах першого операнда, то результат буде беззмістовним.

Зазначимо, що зсув ліворуч відповідає множенню першого операнда на степінь числа 2, що дорівнює другому операнду, а зсув праворуч ді- ленню першого операнда на 2 у степені, що дорівнює другому операнду.

Побітові операції: & (кон'юнкція), ^ (додавання за модулем 2) та |

(диз'юнкція). Усі побітові операції комутативні й асоціативні.

Під час виконання операції & порівнюється кожен біт першого опе- ранда з відповідним бітом другого. Якщо обидва біти одиниці, то відповідний біт результату буде 1, інакше – 0.

304

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

Під час виконання операції | порівнюється кожен біт першого опе- ранда з відповідним бітом другого. Якщо один із бітів – 1, то відпові- дний біт результату буде 1, інакше – 0.

Під час виконання операції ^ порівнюється кожен біт першого опера- нда з відповідними бітами другого. Якщо один із порівнюваних бітів до- рівнює 0, а другий – 1, то відповідний біт результату буде 1, інакше – 0.

Приклад 3.23.

Вираз

Значення

int i=3;

000011002

i<<2

i>>2

000000002

і& ~07

00000011 & ~00000111==00000011 & 111111000

 

==00000000

іnt i=0x1234, j, k;

k=0x2340

k=i<<4;

j=i<<8;

j=0x3400

і=j>>8;

i=0x0034

іnt i=0x45FF,

i=0100 0101 1111 1111

j=0x00FF,

j=0000 0000 1111 1111

r;

 

r=i^j;

r=0x4500=0100 0101 0000 0000

r=і|j;

r=0x45FF=0100 0101 0000 0000

r=i&j;

r=0x00FF=0000 0000 1111 1111

 

Логічні цілі операції:

<логічна-ціла-операція>::=<відношення> | <булева-операція> <відношення>::=<|<=|>|>=|==| != <булева-операція>::=! |&&| ||

Результат відношення e1 e2 буде 1, якщо відношення виконуєть- ся (e1 менше, не більше, більше, не менше, дорівнює, не дорівнює e2), інакше – 0.

Булеві операції && та || трактуються як тризначні й набувають одного із трьох значень: 1, 0 або # (див. табл. 1.1). В обох операціях першим об- числюється лівий операнд. Якщо він істинний (у випадку диз'юнкції) чи хибний (у випадку кон'юнкції), то другий операнд не обчислюється. Опе- рацію заперечення ! розглянуто вище.

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

305

ПРОГРАМУВАННЯ

пами теж слід ураховувати скінченність моделей. Це зумовлює такі їхні особливості, як нерівномірну щільність, переповнення при вико- нанні операцій і беззмістовність у моделі дійсних поза межами діапа- зону типу (див. підрозд. 2.3.3):

<cпецифікатор-дійсного-типу>::=float |double|long double

Стандарт С99 вимагає, щоб характеристики дійсних типів були прописані в заголовному файлі float.h (табл. 3.9).

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

Стандартні функції для роботи з дійсними типами містяться в біб- ліотеці <math.h> (табл. 3.10). Усі функції повертають значення типу double. Кути в тригонометричних функціях задаються в радіанах.

Таблиця 3.9. Деякі граничні дійсні константи з файла float.h

Константа

Значення

Визначення

FLT_DIG

6

Кількість десяткових цифр у мантисі для типу float

FLT_EPSILON

1E-5

Машинний нуль у типі float

FLT_MAX

1E +37

Максимальне значення в типі float

FLT_MIN

1E-37

Мінімальне значення в типі float

FLT_MIN_EXP

 

Найменше n таке, що 10n належить типу float

DBL_DIG

10

Кількість десяткових цифр у мантисі в типі double

DBL_EPSILON

1E-9

Машинний нуль min{x :1.0+x 1.0} у типі double

DBL_MAX

1E +37

Максимальне значення в типі double

DBL_MIN

1E-37

Мінімальне значення в типі double

DBL_MIN_EXP

 

Найменше n таке, що 10n належить типу double

Таблиця 3.10. Деякі з функцій бібліотеки <math.h>. double x,y; int n;

Функція

sin(x)

cos(x)

tan(x)

asin(x)

atan(x)

exp(x)

log(x)

log10(x)

Визначення

Синусx Косинус x Тангенс x

Арксинус x , x [1,1] Арктангенс x Експонента ex

ln(x ),x > 0 log10 (x ),x > 0

306

 

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

 

Закінчення табл. 3.10.

Функція

Визначення

pow(x,y)

 

Степінь xy

sqrt(x)

ceil(x)

floor(x)

fabs(x)

frexp(x,int *exp)

modf(x, double *ip)

x , x 0

Найближче до x ціле в типі double, не менше за x Найближче до x ціле в типі double, не більше за x

x

Повертає нормалізовану мантису m у діапазоні [1/2,1) і двійковий порядок 2p , який зберігається за

адресою exp. Таким чином, x =m * 2p . Для x = 0 обидві частини результату теж дорівнюють 0

Виділяє цілу й дробову частини, що мають знак, однаковий із x . Ціла частина зберігається за адре-

сою ip , дробова повертається як результат

Символьні змінні:

<cпецифікатор-символьного-типу>::=char|signed char|unsigned char

Тип char цілий. Незважаючи на те, що зазвичай він використову- ється для збереження символів, його доцільно використовувати і для збереження маленьких (до 255) цілих значень. Семантично тип сhar на- лежить до цілочислових типів розміром 1 байт. На ньому визначена вся цілочислова арифметика. Символьні дані можуть зустрічатися в ариф- метичних виразах. Значеннями їх є числові коди символів. Наприклад, ‘0'+2=48+2=50 тощо. Тип char залежно від реалізації може бути беззна- ковим або знаковим. Ураховуючи, що функції консольного введення- виведення по досягненні кінця файла повертають від'ємне значення, задане макросом ЕОF, при читанні символів безпечніше використовува- ти знакову змінну типу int, а не char, яка може виявитися беззнаковою.

Булеві змінні. Беззнаковий цілий тип _Bool з'явився у С99 і скла- дається із двох значень: 0 (хиба), 1 (істина). При перетвореннях ска- лярних виразів29 до булевого типу ненульові значення перетворюють- ся на 1, а решта на – 0. У заголовному файлі stdbool.h визначено ма- крос bool як синонім для типу _Bool, а також false та true для 0 та 1. На булевому типі визначено всі логічні операції.

29 До скалярних належать усі неструктуровані типи числові, символьні й покажчики.

307

ПРОГРАМУВАННЯ

3.2.4. ПОРЯДКОВІ ТИПИ

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

<порядковий-тип>::=enum [<ім'я-тегу>]\ \{<ім'я>[=<константний-вираз>],\ {<ім'я>[=<константний-вираз>]}\}

Тегом називається конструкція у фігурних дужках зі списком по- іменованих констант. Тег може мати своє ім'я, що записується відра- зу після ключового слова enum. Усі константи в описі мають цілий тип.

Приклад 3.24.

еnum {saturday=6, sunday=7} frееday;

еnum weekend {saturday=6, sunday=7} frееday; еnum weekend freeday;

В останньому рядку ім'я тегу weekend дозволяє використовувати тег типу повторно без перерахування його значень ■

Порядковим константам значення призначаються: 1) за допомогою константного виразу в описі типу:

еnum weekend {saturday=6, sunday=saturday+1};

2)якщо немає явного присвоювання значення, то перша константа отримує значення 0;

3)поточна константа в разі відсутності явного присвоювання отри- мує значення на 1 більше, ніж значення попередньої константи.

Приклад 3.25. В описі типу

enum wage {small, medium=50, pretty_med, large=90};

константи small, medium, pretty_med та large мають значення від-

повідно 0, 50, 51 та 90 ■ На порядкових типах діє ціла арифметика.

308

Розділ ІІІ. МОВИ ПРОГРАМУВАННЯ С ТА С++

3.2.5. СУМІСНІСТЬ, ЗВЕДЕННЯ Й УЗГОДЖЕНІСТЬ ТИПІВ

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

Стандартні числові типи сумісні тільки тоді, коли вони ідентичні, тобто коли їм відповідає одна сукупність об'єктів (за розміром і струк- турою полів, а також рівнем доступу). При описі типу можуть опуска- тися деякі специфікатори й навіть назви типів, але всі ці його форми є ідентичними й задають один тип. Наприклад, типи short та short int ідентичні, а отже, сумісні, а типи unsigned, int та short неіден- тичні й несумісні. Тип const int не сумісний із жодним варіантом типу int (різний рівень доступу).

Кожне визначення порядкового типу породжує новий цілий тип, який за С99 є сумісним із базовим цілим типом його констант. Жодні два різних порядкових типи, визначені у вхідному файлі, не є суміс- ними. Однак зліченні типи сумісні, якщо в одному з них визначається тег з іменем, а в другому використовується ім'я цього тегу. Напри- клад, типи змінних x та y в операторах

еnum s {p, q} x; еnum s y;

єсумісними.

Варифметичних виразах мови C дозволяється змішувати типи числових операндів, що є природним у застосуваннях. Наприклад,

коректним є вираз sqrt (b * b 4 * a * c ), який обчислює дискримінант квадратного рівняння з дійсними коефіцієнтами a,b,c . Це ускладнює

реалізацію виразів, оскільки ті самі ціла й дійсна арифметики суттєво відрізняються (як поданням об'єктів у ОП, так і реалізацією операцій). Щоб урегулювати за необхідності розбіжність типів операндів, на чи- слових типах установлено лінійний порядок, який базується на діапа- зонах їхніх значень:

char <unsigned char <short <unsigned short <int <unsigned int <long <unsigned long <long long <float <double <long double

Згідно із цим порядком кожний числовий вираз має свій тип, яким є старший із типів його операндів. Це не стосується виразів присвою- вання, тип яких збігається з типом l -виразу в лівій частині.

309

ПРОГРАМУВАННЯ

У процесі обчислення значення виразу всі операнди автоматично зводяться до його типу. Зведення до типу може вимагатися й у таких ситуаціях:

в операціях примусового зведення до типу;

при ініціалізації параметрів функції (значення фактичного пара- метра зводиться до типу формального параметра);

при виході з функції значення, що повертається, зводиться до типу її результату.

У процесі зведення операнда до іншого типу може змінюватися як розмір зв'язаного з ним об'єкта, так і внутрішня його структура.

Тип даних T1 називається узгодженим із типом T 2 , якщо визна-

чене правило зведення констант типу T1 до типу T 2 .

Зведення цілих типів. Здійснюється, коли вираз має один із ці- лих типів. Якщо тип зведення дозволяє точно подати значення вира- зу, то останнє перетворюється до нього, інакше до беззнакового ти-

пу unsigned int, unsigned long або unsigned long long. При перетво-

ренні беззнакових цілих до знакових того самого розміру виникає си- туація переповнення, якщо старший біт беззнакового цілого є 1. Пе- ретворення від'ємного цілого до беззнакового невизначене. При пере- творенні беззнакових цілих до коротших беззнакових відкидаються зайві старші розряди.

Зведення цілих і дійсних типів. При перетворенні значень із дій- сного типу на цілочисловий дробова частина відкидається; якщо отри- мане ціле міститься за межами даного цілого типу, то результат неви- значений. Зокрема, дана ситуація має місце при перетворенні від'єм- них дійсних до беззнакових цілих. Якщо ціле значення перетворюється до дійсного й міститься в допустимому діапазоні, але подається неточ- но, то результатом буде найближче до даного цілого дійсне.

Зведення дійсних типів. При перетворенні меншого типу до бі- льшого значення не змінюється. Навпаки, якщо перетворюється зна- чення від старшого типу до молодшого, яке міститься в діапазоні ме- ншого типу, то результатом буде найближче до нього значення в ме- ншому типі (округлення). Якщо результат виходить за межі меншого типу, то він невизначений.

Зведення типів у операціях присвоювання. При обчисленні значення виразу операнд e2 перетворюється до типу лівого операнда за вказаними вище правилами.

Унарні зведення. Призначені для автоматичної стандартизації типів операндів операцій і аргументів функцій. Наприклад, у С89 усі дійсні аргументи функцій бібліотеки <math.h> автоматично перетво- рюються до типу double. Унарні перетворення наведені в табл. 3.11.

310