Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Auto, extern, register, static, mutable 12 страница




Код програми 9.5. Демонстрація механізму використання глобальних static-змінних

// --------------------Перший файл-------------------

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

int srZnach(int izm); // Обчислення поточного середнього значення.

void reset();// Очищення глобальних змінних.

 

int main ()

{

int num;

do {

cout << "Введіть число (-1 для виходу, -2 для скидання): ";

cin >> num;

if (num==-2) {

reset();

continue;

}

if fun(num!= -1)

cout << "Середнє значення дорівнює: " << srZnach(num);

cout << "\n";

} while (num!= -1);

 

getch (); return 0;

}

// -------------------Другий файл--------------------

static int sum=0, count = 0;

int srZnach(int izm) // Обчислення поточного середнього значення.

{

sum = sum + izm;

count++;

 

return sum / count;

}

 

void reset() // Очищення глобальних змінних.

{

sum = 0;

count = 0;

}

У цій версії програми змінні sum і count є глобально статичними, тобто їх глобальність обмежена другим файлом. Отже, вони використовуються функціями srZnach() і reset(), причому обидві вони розташовані в другому файлі. Цей варіант програми дає змогу скидати нагромаджену суму (шляхом встановлення в початкове положення змінних sum і count), щоб можна було усереднити інший набір чисел. Але жодна з функцій, розташованих поза другим файлом, не може отримати доступ до цих змінних. Працюючи з цією програмою, можна очистити попередні нагромадження, ввівши число -2. У цьому випадку буде викликано функцію reset(). Перевірте це. Окрім того, спробуйте отримати з першого файлу доступ до будь-якої із змінних sum або count[36].

Отже, ім'я локальної static -змінної відоме тільки функції або блоку коду програми, у якому вона оголошена, а ім'я глобальної static -змінної – тільки файлової, у якому вона "мешкає". По суті, модифікатор static дає змогу змінним існувати так, що про них знають тільки функції, які використовують їх, тим самим "тримаючи у шорах" і обмежуючи можливості негативних побічних ефектів. Змінні типу static дають змогу програмісту "приховувати" одні частини своєї програми від інших. Це може виявитися просто суперперевагою, коли Вам доведеться розробляти дуже велику і складну програму.

Варто знати! Попри те, що глобальні static -змінні, як і раніше, допускаються і широко використовуються в С++-програмі, стандарт мови C++ заперечує проти їх застосування. Для керування доступом до глобальних змінних рекомендуємо інший метод, який полягає у використанні просторів імен. Цей метод буде описано далі (див. розд. 21.1).

9.2.4. Регістрові змінні

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

Специфікатор класу пам'яті register в визначенні змінної означає вимогу оптимізувати код для отримання максимально можливої швидкості доступу до неї.

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

Оскільки насправді тільки для обмеженої кількості змінних можна забезпечити швидкий доступ, то важливо ретельно вибрати, до яких з них застосувати модифікатор register [37]. Як правило, ніж частіше до змінної потрібен доступ, тим більша вигода буде отримана внаслідок оптимізації коду програми за допомогою специфікатора класу пам'яті register. Тому оголошувати регістровими має сенс змінні параметри циклу, або змінні, до яких здійснюється доступ в тілі циклу. На прикладі наведеної нижче функції показано, як register -змінна типу int використовують для керування циклом. Ця функція обчислює результат виразу me для цілочисельних значень із збереженням знаку початкового числа (тобто при m = -2 і е = 2 результат буде дорівнювати -4).

int signed_pwr(register int m, register int e)

{

register int tmp;

int znak;

 

if (m < 0) znak = -1;

else znak = 1;

 

tmp = 1;

for (; e; e--) tmp = tmp * m;

 

return tmp * znak;

}

У наведеному прикладі змінні m, e і tmp оголошені як регістрові, оскільки всі вони використовуються в тілі циклу, і тому до них часто здійснюється доступ. Проте змінна znak оголошена без специфікатора класу пам'яті register, оскільки вона не є частиною циклу і використовується рідше.

9.2.5. Походження модифікатора register

Модифікатор register був вперше визначений у мові С. Спочатку він застосовувався тільки до змінних типу int і char або до покажчиків і примушував зберігати змінні цього типу в регістрі ЦП, а не в ОЗП, де зберігаються звичайні змінні. Це означало, що операції з регістровими змінними могли виконуватися набагато швидше, ніж операції з іншими (що зберігаються в пам'яті), оскільки для запиту або модифікації їх значень не потрібен був доступ до пам'яті.

Після стандартизації мови C було ухвалене рішення розширити визначення специфікатора класу пам'яті register. Згідно з ANSI-стандартом мови С, модифікатор register можна застосовувати до будь-якого типу даних. Його використання стало означати для компілятора вимогу зробити доступ до змінної типу register максимально швидким. Для ситуацій, що містять символи і цілочисельні значення, це, як і раніше, означає занесення їх у регістри ЦП, тому традиційне визначення все ще є в силі. Оскільки мова C++ побудована на ANSI-стандарті мови С, то він також підтримує розширене визначення специфікатора класу пам'яті register.

Як ми вже зазначали вище, точна кількість register -змінних, які реально будуть оптимізовані в будь-якій одній функції, визначається як типом процесора, так і конкретною реалізацією мови програмування C++, яку Ви використовуєте. У загальному випадку можна розраховувати принаймні на дві. Проте не варто турбуватися про те, що Ви могли оголосити дуже багато register -змінних, оскільки мова C++ автоматично перетворить регістрові змінні на нерегістрові, коли їх ліміт буде вичерпаний. Це гарантує перенесність С++-коду програми у межах широкого діапазону процесорів.

Щоб показати вплив, що надається register -змінними на швидкодію програми, у наведеному нижче прикладі вимірюється час виконання двох циклів for, які відрізняються один від одного тільки типом змінних, що ним керують. У програмі використовується стандартна бібліотечна С++-функція clock (), яка повертає кількість імпульсів сигналу часу системного годинника, підрахованого з початку виконання цієї програми. Програма повинна містити заголовок <ctime>.

Код програми 9.6. Демонстрація впливу використання register-змінної на швидкість виконання програми

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

#include <ctime> // Для використання системного часу і дати

using namespace std; // Використання стандартного простору імен

 

unsigned int i; // Не register -змінна

unsigned int delay;

 

int main ()

{

register unsigned int j;

long start, end;

start = clock ();

for (delay=0; delay<50; delay++)

for (i=0; i < 64000000; i++);

end = clock ();

cout << "Кількість тиків для не register -циклу: ";

cout << end-start << "\n";

 

start = clock ();

for (delay=0; delay<50; delay++)

for (j=0; j < 64000000; j++);

end = clock ();

cout << "Кількість тиків для register -циклу: ";

cout << end-start << "\n";

 

getch (); return 0;

}

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

Необхідно пам'ятати! Під час написання цього навчального посібника було використано середовище C++Builder 6, яке ігнорує ключове слово register. C++Builder 6 застосовує оптимізацію "як вважає за потрібне". Тому Ви можете не помітити впливу специфікатора класу пам'яті register на виконання попередньої програми. Проте ключове слово register все ще приймається компілятором без повідомлення про помилку. Воно просто не спонукає до ніякої дії.

9.3. Порозрядні оператори

Оскільки мова C++ спрямована на те, щоб відкрити повний доступ до апаратних засобів комп'ютера, важливо, щоб оператор мав можливість безпосередньо впливати на окремі біти у межах байта або машинного слова. Саме тому мова програмування C++ і містить порозрядні оператори, призначені для тестування, встановлення або зсуву реальних бітів у байтах або словах, які відповідають символьним або цілочисельним С++-типам даних. Порозрядні оператори не використовуються для операндів типу bool, float, double, long double, void або інших ще складніших типів даних.

Порозрядні оператори обробляють окремі біти.

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

Табл. 9.1. Порозрядні оператори оброблення окремих бітів

Оператор Значення
& Порозрядне І (AND)
ï Порозрядне АБО (OR)
^ Порозрядне виключення АБО (ХОR)
>> Зсув вправо
<< Зсув вліво
~ Доповнення до І (унарний оператор НЕ)

9.3.1. Порозрядні оператори І, АБО, що виключає АБО і НЕ

Порозрядні оператори І, АБО, що виключають АБО і НЕ (що позначаються символами &, |, ^ і ~ відповідно) виконують ті самі операції, що і їх логічні еквіваленти (тобто вони діють згідно з тією ж таблицею істинності). Відмінність полягає тільки у тому, що порозрядні операції працюють на побітовій основі. У наведеній нижче таблиці показано результат виконання кожної порозрядної операції для всіх можливих поєднань операндів (нулів і одиниць).

Табл. 9.1. Результат виконання порозрядних операцій поєднань операндів

р q р & q р|а р ^ а
           
           
           
           

Як видно з цієї таблиці, результат застосування оператора ХОR (що виключає АБО) буде дорівнювати значенню ІСТИНА (1) тільки у тому випадку, якщо істинний (дорівнює значенню 1) тільки один з операндів; інакше результат приймає значення ФАЛЬШ (0).

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

1101 0011

& 1010 1010

1000 0010

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

Код програми 9.7. Демонстрація перетворення рядкових букв у прописні

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

int main ()

{

char ch;

 

do {

cin >> ch;

 

// Ця настанова онулює 6-й біт.

ch = ch & 223; // В змінної ch тепер прописна буква.

 

cout << ch;

} while (ch!='Q');

 

getch (); return 0;

}

Значення 223, що використовується в настанові порозрядного І, є десятковим представленням двійкового числа 1101 1111. Отже, ця операція І залишає всі біти в змінній ch незайманими, за винятком шостого (він скидається в нуль).

Оператор І також корисно використовувати, якщо потрібно визначити, чи встановлено біт, який Вас зацікавив, тобто чи дорівнює він значенню 1 чи ні. Наприклад, у процесі виконання такої настанови можна дізнатися, чи встановлено 4-й біт у змінній status:

if (status & 8) cout << "Біт 4 встановлено";

Щоб зрозуміти, чому для тестування четвертого біта використовують число 8, пригадаймо, що в двійковій системі числення число 8 представляється як 0000 1000, тобто в числі 8 встановлено тільки четвертий розряд. Тому умовний вираз у настанові if дасть значення ІСТИНА тільки у тому випадку, якщо четвертий біт змінної status також встановлено (дорівнює 1). Цікаве використання цього методу показано на прикладі функції disp_binary(). Вона відображає в двійковому форматі конфігурацію бітів свого аргументу. Будемо використовувати функцію disp_binary() нижче у цьому підрозділі для дослідження можливостей інших порозрядних операцій:

// Відображення конфігурації бітів у байті

void disp_binary(unsigned u)

{

register int t;

 

for (t=128; t>0; t = t/2)

if (u & t) cout << "1 ";

else cout << "0 ";

cout << "\n";

}

Функція disp_binary(), використовуючи порозрядний оператор І, послідовно тестує кожен біт молодшого байта змінної u, щоб визначити, встановлений він чи скинутий. Якщо він встановлений, то відображається цифра 1, інакше цифра 0. Заради інтересу спробуйте розширити цю функцію так, щоб вона відображала всі біти змінної І, а не тільки її молодший байт.

Порозрядний оператор АБО, на противагу порозрядному оператору І, зручно використовувати для встановлення потрібних бітів у одиницю. У процесі виконання операції АБО наявність в будь-якому операнді біта, що дорівнює 1, означає, що в результаті відповідний біт також буде дорівнювати одиниці. Ось приклад.

1101 0011

| 1010 1010

1111 1011

Можна використовувати оператор АБО для перетворення розглянутої вище програми (яка перетворить рядкові символи в їх прописні еквіваленти) в її "протилежність", тобто тепер, як це показано нижче, вона перетворюватиме прописні букви у рядкові.

Код програми 9.8. Демонстрація перетворення прописних букв у рядкові

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

int main ()

{

char ch;

do {

cout << "Введіть прописну букву: "; cin >>ch;

 

/* Ця настанова робить букву рядковою,

встановлюючи її 6-й біт. */

ch = ch | 32;

cout << "\nРядкова буква: " << ch << "\n";

} while (ch!= 'q');

 

getch (); return 0;

}

Встановлення шостого біта перетворює прописну букву на її рядковий еквівалент.

Порозрядне виключення АБО (ХОR) встановлює в одиницю біт результату тільки у тому випадку, якщо відповідні біти операндів відрізняються один від одного, тобто вони є не однаковими. Ось приклад:

0111 1111

^ 1011 1001

1100 0110

Унарний оператор НЕ (або оператор доповнення до 1) інвертує стан усіх бітів свого операнда. Наприклад, якщо цілочисельне значення (що зберігається в змінній А), є двійковим кодом 1001 0110, то в результаті виконання операції ~А отримаємо двійковий код 0110 1001.

У наведеному нижче коді програми продемонстровано механізм використання оператора НЕ шляхом відображення деякого числа і його доповнення до 1 у двійковому коді за допомогою наведеної вище функції disp_binary().

Код програми 9.9. Демонстрація механізму використання оператора НЕ

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

void disp_binary(unsigned u);

 

int main ()

{

unsigned u;

 

cout << "Введіть число між 0 і 255: "; cin >> u;

 

cout << "Початкове число в двійковому коді: ";

disp_binary(u);

 

cout << "Його доповнення до одиниці: ";

disp_binary(~u);

 

getch (); return 0;

}

 

// Відображення бітів, з яких складається байт.

void disp_binary(unsigned u)

{

register int t;

 

for (t=128; t>0; t = t/2)

if (u & t) cout << "1 ";

else cout << "0 ";

cout << "\n";

}

Ось як виглядають результати виконання цієї програми.

Введіть число між 0 і 255: 99

Початкове число в двійковому коді: 01100011

Його доповнення до одиниці: 10011100

Варто знати! Не плутайте логічні та порозрядні оператори. Вони виконують різні дії. Оператори &, | і ~ застосовуються безпосередньо до кожного біта значення окремо. Еквівалентні логічні оператори обробляють як операнди значення ІСТИНА/ФАЛЬШ (не нуль/нуль). Тому порозрядні оператори не можна використовувати замість їх логічних еквівалентів у умовних виразах. Наприклад, якщо значення х дорівнює 7, то вираз x && 8 має значення ІСТИНА, тоді як вираз x & 8 дає значення ФАЛЬШ.

Необхідно пам'ятати! Оператор відношення або логічний оператор завжди генерує результат, який має значення ІСТИНА або ФАЛЬШ, тоді як аналогічний порозрядний оператор генерує значення, що отримується згідно з таблицею істинності конкретної операції.

9.3.2. Оператори зсуву

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

значення >> кількість_бітів,

а оператор зсуву вліво використовують так:

значення << кількість_бітів.

У цьому записі елемент кількість_бітів вказує, на скільки позицій потрібно зсунути значення. Під час кожного зсування вліво всі біти, що складають значення, зсуваються вліво на одну позицію, а у молодший розряд записують нуль. Під час кожного зсування вправо всі біти зсуваються, відповідно, вправо. Якщо зсуву вправо піддається значення без знаку, то в старший розряд записують нуль. Якщо ж зсуву вправо піддається значення зі знаком, то значення знакового розряду зберігається. Як Ви пам'ятаєте, негативні цілі числа представляються встановленням старшого розряду числа, що дорівнює одиниці. Таким чином, якщо зсовуване значення є негативним, то під час кожного зсування вправо в старший розряд записують одиницю, а якщо позитивне – нуль. Не забувайте, зсув, що виконується оператора|ми зсуву, не є циклічним, тобто при зсуванні як вправо, так і вліво крайні біти втрачаються, і вміст втраченого біта дізнатися неможливо.

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

Оператори зсуву працюють тільки зі значеннями цілочисельних типів, наприклад, символами, цілими числами і довгими цілими числами. Вони не застосовуються до значень з плинною крапкою.

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

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

Код програми 9.10. Демонстрація виконання операторів порозрядного зсуву

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

 

void disp_binary(unsigned u);

 

int main ()

{

int izm=1, t;

for (t=0; t<8; t++) {

disp_binary(izm);

izm = izm << 1;

}

 

cout << "\n";

 

for (t=0; t<8; t++) {

izm = izm >> 1;

disp_binary(izm);

}

 

getch (); return 0;

}

 

// Відображення бітів, з яких складається байт.

void disp_binary(unsigned u)

{

register int t;

 

for (t=128; t>0; t=t/2)

if (u & t) cout << "1 ";

else cout << "0 ";

cout << "\n";

}

Результати виконання цієї програми є такими:

0 0 0 0 0 0 0 1

0 0 0 0 0 0 1 0

0 0 0 0 0 1 0 0

0 0 0 0 1 0 0 0

0 0 0 1 0 0 0 0

0 0 1 0 0 0 0 0

0 1 0 0 0 0 0 0

1 0 0 0 0 0 0 0

 

1 0 0 0 0 0 0 0

0 1 0 0 0 0 0 0

0 0 1 0 0 0 0 0

0 0 0 1 0 0 0 0

0 0 0 0 1 0 0 0

0 0 0 0 0 1 0 0

0 0 0 0 0 0 1 0

0 0 0 0 0 0 0 1

9.4. Спеціальні оператори розширення можливостей мови С++

Вище у цьому навчальному посібнику Ви вже познайомилися з більшістю операторів, які не є унікальними у мові C++. Але, на відміну від інших мов, у мові програмування C++ передбачено і інші спеціальні оператори, які значно розширюють можливості мови і підвищують її гнучкість. Цим операторам і присвячено частину підрозділу, що залишилася.

9.4.1. Перерахунки – списки іменованих цілочисельних констант

У мові програмування C++ можна визначити список іменованих цілочисельних констант. Такий список називається перерахунком (enumeration). Ці константи можна потім використовувати скрізь, де допускаються цілочисельні значення (наприклад, в цілочисельних виразах). Перерахунки визначаються за допомогою ключового слова enum, а формат їх визначення має такий вигляд:

enum type_name { список_перерахунку } список_змінних;

Під елементом список_перерахунку розуміють список розділених між собою комами імен, які представляють значення перерахунку. Елемент список_змінних є необов'язковим, оскільки змінні можна оголосити пізніше, використовуючи ім'я типу перерахунку. У наведеному нижче прикладі визначається перерахунок apple і дві змінні типу apple з іменами red і yellow:

enum apple {Jonathan Golden_Del, Red_Del, Winesap,

Cortland, McIntosh} red, yellow;

Визначивши перерахунок, можна оголосити інші змінні цього типу, використовуючи ім'я перерахунку. Наприклад, за допомогою такої настанови оголошується одна змінна fruit перерахунку apple:

apple fruit;

Цю настанову можна записати і так:

enum apple fruit;

Ключове слово enum оголошує перерахунок.

Проте використання ключового слова enum тут є зайвим. У мові програмування С (яка також підтримує перерахунки) обов'язковою була друга форма, тому в деяких програмах Ви можете натрапити на подібний запис.

З урахуванням попередніх оголошень наведені нижче типи настанов абсолютно допускаються:

fruit = Winesap;

if (fruit==Red_Del) cout << "Red Delicious\n";

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




Поделиться с друзьями:


Дата добавления: 2014-11-29; Просмотров: 540; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.01 сек.