Оператори мови з
Лекція 2. Оператори мови С ++.
структура програми
Оператори керують процесом виконання програми. Набір операторів мови С ++ містить всі керуючі конструкції структурного програмування.
Складовою оператор обмежується фігурними дужками. Всі інші оператори закінчуються крапкою з комою.- Порожній оператор -;
while (<выражение> ) <оператор>
do<оператор>while<выражение> ; У мові C ++ цей оператор відрізняється від класичної реалізації циклу з умовою поста тим, що при істинності вираження відбувається продовження роботи циклу, а не вихід із циклу.
for ([<начальное выражение> ]; [<условное выражение> ]; [<выражение приращения> ]) <оператор>
Тіло оператора for виконується до тих пір, поки умовний вираз не стане хибним (рівним 0). Початкове вираз і вираз збільшення зазвичай використовуються для ініціалізації і модифікації параметрів циклу та інших значень. Початкове вираз обчислюється один раз до першої перевірки умовного виразу. а вираз збільшення обчислюється після кожного виконання оператора. Будь-яке з трьох виразів заголовка циклу, і навіть всі три можуть бути опущені (не забувайте тільки залишати крапки з комою). Якщо опущено умовний вираз. то воно вважається істинним, і цикл стає нескінченним.
Оператор покрокового циклу в мові С ++ є гнучкою і зручною конструкцією, тому оператор циклу з передумовою while використовується в мові С ++ вкрай рідко, тому що в більшості випадків зручніше користуватися оператором for.break; Оператор розриву перериває виконання операторів while. do. for і switch. Він може міститися тільки в тілі цих операторів. Управління передається оператору програми, наступного за перерваним. Якщо оператор розриву записаний всередині вкладених операторів while. do. for. switch. то він завершує тільки безпосередньо охоплює його оператор.
continue; Оператор продовження передає управління на наступну ітерацію в операторах циклу while. do. for. Він може міститися тільки в тілі цих операторів. В операторах do і while наступна ітерація починається з обчислення умовного виразу. В операторі for наступна ітерація починається з обчислення виразу збільшення, а потім відбувається обчислення умовного виразу.
return [<выражение> ];
Оператора повернення закінчує виконання функції, в якій він міститься, і повертає управління в зухвалу функцію. Управління передається в точку викликає функції, безпосередньо наступну за оператором виклику. Значення виразу. якщо вона задано, обчислюється, приводиться до типу, оголошеному для функції, що містить оператор повернення, і повертається в зухвалу функцію. Якщо вираз опущено, то повертається функцією значення не визначене.
З формальної точки зору оператори break. continue і return не є операторами структурного програмування. Однак їх використання в обмежених кількостях виправдано, коли вони спрощують розуміння програми і дозволяють уникати великих вкладених структур. Наприклад, ми перевіряємо вхідні дані на аномалії. Якщо не використовувати ці оператори, то всю обробку доведеться вкласти в умовний блок, що погіршує Новомосковскбельность програми. Замість цього можна написати невеликий умовний блок, який організовує вихід з функції при невірних вихідних даних.
Введення / висновок не є частиною мови С ++. а здійснюється функціями, що входять до складу стандартної бібліотеки. Для докладної інформації див. Лекцію 4.
// Помилка - не вказано значення, що повертається // Правильно
Функція з типом void не може повертати значення. Однак виклик функції з типом void не дає значення, так що функція з типом void може використовувати виклик функції з типом void як вираз в інструкції return.
Така форма інструкції return важлива при написанні шаблонів функцій. коли тип значення є параметром шаблону.
2.2.1. Вбудовувані функції
Функцію можна визначити з специфікатором inline. Такі функції називаються вбудованими. Специфікатор inline вказує компілятору, що відкрита підстановка тіла функції краще звичайної реалізації виклику функції і що він повинен намагатися кожного разу генерувати в місці виклику код, відповідний вбудовується функції, а не створювати окремо код функції (одноразово) і потім викликати її за допомогою звичайного механізму виклику. Специфікатор inline не впливає на зміст виклику функції.
Відкрита підстановка не впливає на результати виклику функції, чим відрізняється від макропідстановки. Вбудована функція має звичайний синтаксис опису функції і підпорядковується всім правилам, що стосуються області видимості і контролю типів. Відкрита підстановка є просто інший реалізацією виклику функції. Замість генерації коду, що передає управління і параметри єдиному примірнику тіла функції, копія тіла функції, відповідно модифікована, поміщається на місце виклику. Це економить час для передачі управління.
Для всіх, крім найпростіших, функцій час виконання функцій домінує над витратами часу на обслуговування виклику. З цього випливає, що для всіх, крім найпростіших, функцій економія за рахунок відкритої підстановки мінімальна. Ідеальним кандидатом для відкритої підстановки є функція, що робить щось просте, на зразок збільшення або повернення значення. Існування таких функцій викликається необхідністю обробки прихованих даних.
2.2.2. Параметри функцій за замовчуванням
int g (int m = 1, int n); int h (int m = 1, int n = 2); int h (int m = 1, int n = 2) int h (int m = 0, int n = 0) int f (int m = 1, int n = 2); int f (int m. int n) f (5, 6); f (5); f ();
// Помилка // Правильно // Помилка - повтор параметрів за замовчуванням // Помилка - зміна параметрів за замовчуванням // Правильно // Виклик функції з двома параметрами // Еквівалентно викликом f (5, 2); // Еквівалентно викликом f (1, 2);
2.2.3. параметри програми
Функція main. як і будь-яка інша функція може мати параметри. Ці параметри передаються в програму з командного рядка.
void main (int argc, char * argv [])
// Імена argc і argv не є вимогою мови
2.2.4. Функції зі змінним числом параметрів
Під час інтерпретації списку параметрів така функція користується інформацією, не доступною компілятору. Тому він не в змозі гарантувати, що очікувані параметри дійсно присутні або що вони мають правильні типи. Ясно, що якщо параметр не був оголошений, компілятор не має інформації, необхідної для виконання стандартної перевірки і перетворень типу.
Функцію тільки з неоголошеним параметрами, в принципі, визначити можна, але вибрати параметри буде важко, тому що макроозначення для роботи з неоголошеним параметрами використовують ім'я останнього оголошеного формального параметра.
Усередині функції програміст сам відповідає за вибір з стека додаткових параметрів. Для роботи з ними використовуються макроозначення va_arg. va_start і va_end. певні в файлі stdarg.h.
Приклад програми з функцією з перменная числом параметрів см. В кінці лекції.
2.3. препроцесор
Препроцесор - це програма, яка обробляє текст вашої програми до компілятора. Таким чином, на вхід компілятора потрапляє текст, який може відрізнятися від того, який бачите Ви. Робота препроцесора управляється директивами. За допомогою препроцесора можна виконувати наступні операції:- включення в програму текстів із зазначених файлів;
- заміна ідентифікаторів послідовностями символів;
- макропідстановка. тобто заміна позначення параметризованим текстом, який формується препроцесором з урахуванням конкретних аргументів;
- виключення з програми окремих частин тексту (умовна компіляція).
2.3.1. включення файлів
Включення файлів проводитися за допомогою директиви #include. яка має наступний синтаксис:
#include<путь>#include "шлях"
Кутові дужки тут є елементом синтаксису.
Директива #include включає вміст файлу, шлях до якого заданий, в компільований файл замість рядка з директивою. Якщо шлях укладено в кутові дужки, то пошук файлу здійснюється в стандартних директоріях. Якщо шлях укладений в лапки і заданий повністю, то пошук файлу здійснюється в заданій директорії, а якщо шлях повністю не заданий - в поточній директорії. За допомогою це директиви Ви можете включати в текст програми як стандартні, так і свої файли.
Крім того, як було зазначено вище, в мові С ++ ряд функцій, такі як функції введення / виводу, динамічного розподілу пам'яті і т.д. не є елементом мови, а входять в стандартні бібліотеки. Для того щоб користуватися функціями стандартних бібліотек, необхідно в текст програми включати так звані заголовки (в описі кожної функції вказується, який заголовки необхідний для неї). Це також робиться за допомогою директиви препроцесора #include.
Директива #include може бути вкладеною. Це означає, що вона може зустрітися в файлі, включеному інший директивою #include. Допустимий рівень вкладеності директив #include залежить від реалізації компілятора.
2.3.2. макропідстановки
Макропідстановки реалізуються директивою #define. яка має наступний синтаксис:
#define<идентификатор><текст>#define<идентификатор> (<список параметров> ) <текст>
Директива #define замінює всі входження ідентифікатора в вихідному файлі на текст. Наступного в директиві за ідентифікатором. Цей процес називається макропідстановки. Ідентифікатор замінюється лише в тому випадку, якщо він є окремою лексему. Наприклад, якщо ідентифікатор є частиною рядка або довшого ідентифікатора, він не замінюється.
Текст являє собою набір лексем, таких як ключові слова, константи, ідентифікатори або вираз. Один або більше пробільних символів повинні відокремлювати текст від ідентифікатора (або від ув'язнених в дужки параметрів). Якщо текст не вміщується на рядку, то він може бути продовжений на наступному рядку, для цього слід набрати в кінці рядка символ «зворотний слеш» і відразу за ним натиснути клавішу «ВВЕДЕННЯ».
Текст може бути опущений. В цьому випадку всі екземпляри ідентифікатора будуть видалені з початкового тексту програми. Проте, сам ідентифікатор розглядається як певний.
Список параметрів. якщо він заданий, містить один або більше ідентифікаторів, розділених комами, і повинен бути укладений в круглі дужки. Ідентифікатори в списку повинні відрізнятися один від одного. Їх область дії обмежена Макроозначення, в якому вони задані. Імена формальних параметрів в тексті зазначають позиції, в які повинні бути підставлені фактичні аргументи макровизова.
У макровизове слідом за ідентифікатором записується в круглих скобах список фактичних аргументів, відповідних формальним параметрам зі списку параметрів. Списки фактично і формальних параметрів повинні містити одне і те ж кількість елементів. Не слід плутати підстановку аргументів на макроозначень з передачею аргументів функції. Підстановка в препроцесорів носить чисто текстовий характер. Ніяких обчислень або перетворень типу при цьому не проводиться.
#define N 100 #define MULT (a, b) ((a) * (b)) #define MAX (x, y) ((x)> (y)). (X). (Y)
Виклик MULT (x + y, z) буде замінений на ((x + y) * (z)). При відсутності внутрішніх дужок вийшло б (x + y * z). що невірно.
Макровиклик MAX (i, a [i ++]) заміниться на ((i)> (a [i ++])). (I). (A [i ++])). Результат обчислення непередбачуваний.
У директиві #define дві лексеми можуть бути «склеєні» разом. Для цього їх потрібно об'єднати знаками ## (зліва і справа допустимі пробільні символи). Препроцесор об'єднує такі лексеми в одну. Наприклад, макровизначеннями #define VAR (i, j) i ## j при макровизове VAR (x, 6) утворює ідентифікатор x6.
Символ #, що поміщається перед аргументом макроозначення, вказує на необхідність перетворення його в символьний рядок. При макровизове конструкція #<формальный параметр> замінюється на "<фактический параметр> ".
Заміни в тексті можна скасувати директивою #undef. яка має наступний синтаксис:
#undef <идентификатор>
Директива #undef скасовує дію поточного визначення #define для ідентифікатора. Щоб скасувати макроозначень, досить задати його ідентифікатор. Завдання списку параметрів не потрібно. Чи не є помилкою застосування директиви #undef до ідентифікатора, який раніше не був визначений або дія якого вже скасовано.
Прийнята в С / С ++ форма макросів є серйозним недоліком мови. Тепер цю форму можна вважати застарілою завдяки наявності більш підходящих засобів мови, таких як шаблони. простору імен. вбудовані функції і константи. Точно також, широке використання привидів типу в будь-якій мові сигналізує про погане проектуванні. Як макроси, так і приведення є частими джерелами помилок. Той факт, що без них можна обійтися, робить програмування на С ++ набагато більш безпечним і елегантним.
2.3.3. умовна компіляція
Умовна компіляція забезпечується в мові С ++ набором команд, які, по суті, керують не компіляцією, а препроцесорної обробкою. Ці директиви дозволяють виключити з процесу компіляції будь-які частини вихідного файлу за допомогою перевірки умов.
#if<константное выражение> [<текст> ] [#elif<константное выражение> [<текст> ]]. [#else [<текст> ]] #endif
Кожній директиві #if в тому ж вихідному файлі повинна відповідати завершальна її директива #endif. Між директивами #if і #endif допускається довільне кількість директив #elif і не більше однієї директиви #else. Якщо директива #else присутній, то між нею і директивою #endif на даному рівні вкладеності не повинно бути інших директив #elif.
Препроцесор вибирає фрагмент тексту для обробки на основі обчислення константного виразу. наступного за кожною директивою #if і #elif. Вибирається текст. наступний за сталою виразом зі значенням «істина». Якщо жодне обмежене константний вираз неправдиве, то препроцесор вибирає текст. наступний за директивою #else. Якщо ж директива #else відсутня, то ніякої текст не вибирається.
Константне вираз може містити препроцесорну операцію defined (<идентификатор> ). Ця операція повертає істинне значення, якщо заданий ідентифікатор в даний момент визначено, в іншому випадку вираз помилково.
#if (sizeof (void *) == 2) #define SDATA #else #define LDATA #endif #if defined (CREDIT) credit (); #elif defined (DEBIT) debit (); #else printerror (); #endif