Мова C в питаннях і відповідях. Частина 5 (FAQ), Різне, Програмні керівництва, статті

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

В: Шукайте бібліотеку regesp (поставляється з багатьма UNIX – системами)
або дістаньте пакет regexp Генрі Спенсера (Henry Spencer)
(Cs.toronto.edu директорій pub / regexp.shar.Z).
Див також питання 17.12.

12.16 Як розбити командний рядок на розділені пробільними літерами
аргументи (щось на зразок argc і argv в main)?

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

Дивись: ANSI Розд. 4.11.5.8; K & R II Разд.B3 c. 250; H & S
Розд. 15.7; PCS c. 178.

13. Lint.

13.1 Ось я написав програму, а вона веде себе дивно. Що в ній не так?

В: Спробуйте спочатку запустити lint (можливо, з ключами-a,-c,-h,
-P). Багато компілятори С виконують насправді тільки половину
завдання, не повідомляючи про ті підозрілих місцях в тексті програми,
які не перешкоджають генерації коду.

13.2 Як мені придушити повідомлення “warning: possible pointer alignment
problem “(” попередження: можлива проблема з вирівнюванням
покажчика “), яке видає lint після кожного виклику malloc?

В: Проблема полягає в тому, що lint зазвичай не знає, і немає можливості
йому про це повідомити, що malloc “повертає покажчик на область
пам’яті, яка належним чином вирівняна для зберігання об’єкта будь-якого
типу “. Можлива псевдореалізація malloc за допомогою # define всередині
# Ifdef lint, яка видалить це повідомлення, але занадто прямолінійний
застосування # define може придушити та інші осмислені повідомлення про
дійсно некоректних виклики. Можливо, буде простіше ігнорувати
ці повідомлення, може бути, робити це автоматично за допомогою grep-v.

13.3 Де знайти ANSI-сумісний lint?

В: Програма, яка називається FlexeLint (у вигляді вихідного тексту з
віддаленими коментарями і перейменованими змінними, придатна
для компіляції на “майже будь-який” системі) може бути замовлена ​​по
адресою

  Gimpel Software
  3207 Hogarth Lane
  Collegeville, PA  19426  USA
  (+1) 610 584 4261
  gimpel@netaxs.com

Lint для System V release 4 ANSI-сумісний і може бути отриманий
(Разом з іншими C утилітами) від UNIX Support Labs або від
дилерів System V.

Інший ANSI-сумісний LINT (здатний також виконувати формальну
верифікацію високого рівня) називається LCLint і доступний через
ftp:  larch.lcs.mit.edu://pub/Larch/lclint/ .

Нічого страшного, якщо програми lint немає. Багато сучасних
компілятори майже настільки ж ефффектівно у виявленні помилок і
підозрілих місць, як і lint.


14. Стиль.

14.1 Чи може простий і приємний трюк

  if(!strcmp(s1, s2))

служити зразком хорошого стилю?

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

Є альтернативний прийом, пов’язаний з використанням макросу

  #define Streq(s1, s2) (strcmp((s1), (s2)) == 0)

Питання стилю програмування, як і проблеми віри, можуть
обговорюватися нескінченно. До хорошого стилю варто прагнути, він легко
пізнаваний, але не визначимо.

14.2 Який найкращий стиль зовнішнього оформлення програми?

В: K & R, наводячи приклад, якому найчастіше йдуть, забезпечили його
приміткою, що надає Вам остаточний вибір:

Положення дужок менш важливо, хоча люди схильні проявляти
фанатизм у таких питаннях. Ми обрали один з декількох
популярних стилів. Виберіть той стиль, який Вам більше
підходить, і точно йому слідуйте.

Не так важливо, щоб стиль був “ідеальний”. Важливіше, щоб він застосовувався
послідовно і був сумісний (зі стилем колег або загальнодоступних
програм). Якщо вимоги до програмування (місцеві правила або
вимоги фірми) не стосуються стилю, і Ви не відчуваєте бажання
винайти свій власний стиль, то просто слідуйте K & R.

(Давайте не будемо повторювати нескінченні суперечки про переваги та
недоліки того чи іншого розташування відступів і дужок. Див також
        Indian Hill Style Guide).

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

Дивись: K & R Розд. 1.2 c. 10.

14.3 Де дістати “Indian Hill Style Guide” та інші рекомендації по стилю
програмування?

В: Різні документи доступні через ftp:

Сервер: Файл або директорій:

cs.washington.edu ~ftp/pub/cstyle.tar.Z
(128.95.1.4) (перероблений Indian Hill guide)

cs.toronto.edu doc/programming

                ftp.cs.umd.edu          pub/style-guide

15. Операції з плаваючою крапкою.

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

В: Спочатку переконайтеся, що підключений головний файл і правильно
оголошені інші функції, які повертають тип double.

Якщо справа не в цьому, згадайте, що більшість комп’ютерів використовують
формати з плаваючою крапкою, які хоч і схоже, але зовсім не
ідеально імітують операції з дійсними числами. Втрата
значущості, накопичення помилок і інші властиві ЕОМ особливості
обчислень можуть бути досить болючими.

Не потрібно припускати, що результати операцій з плаваючою точкою
будуть точними, особливо не варто перевіряти на рівність два числа
з плаваючою крапкою. (Слід уникати будь-яких непотрібних випадкових
факторів.)

Всі ці проблеми однаково властиві як С, так і іншим мовам
програмування. Семантика операцій з плаваючою точкою визначається
зазвичай так, “як це виконує процесор”; інакше компілятор змушений
б був займатися непомірно дорогою емуляцією “правильної”
моделі обчислень.

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

Дивись: EoPS Розд. 6 c. 115-8.

15.2 Я намагаюся виконати деякі обчислення, пов’язані з тригонометрії,
включаю , але все одно отримую повідомлення: “undefined: _sin”
під час компіляції.

Відповідь: Переконайтеся в тому, що компонувальнику відома бібліотека, в якій
зібрані математичні функції. Наприклад, в операційній системі
UNIX часто необхідний ключ-lm в самому кінці командного рядка.
Див також питання 12.14.

15.3 Чому в мові С немає оператора зведення в ступінь?

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

Дивись: ANSI Розд. 4.5.5.1.

15.4 Як округляти числа?

А: Ось самий простий і чесний спосіб:

   (int)(x + 0.5)

Хоча для негативних чисел це не годиться.

15.5 Як виявити спеціальне значення IEEE NaN та інші спеціальні
значення?

В: Багато компілятори з високоякісної реалізацією стандарту IEEE
операцій з плаваючою точкою забезпечують можливість (наприклад, макрос
isnan ()) явною роботи з такими значеннями, а Numerical C Extensions
Group (NCEG) займається стандартизацією таких коштів. Прикладом
грубого, але зазвичай еффектіного способу перевірки на NaN служить макрос

   #define isnan(x) ((x) != (x))

хоча не знають про IEEE компілятори можуть викинути перевірку в
процесі оптимізації.

15.6 У мене проблеми з компілятором Turbo C. Програма аварійно
завершується, видаючи щось на кшталт “floating point formats not linked.”

Про: Деякі компілятори для міні-ЕОМ, включаючи Turbo C (а також
компілятор Денніса Рітчі для PDP-11), не включають підтримку операцій
з плаваючою точкою, коли їм здається, що це не знадобиться.
Особливо це стосується версій printf і scanf, коли для економії
місця не включається підтримка% e,% f, і% g. Буває так, що
евристичної процедури Turbo C, яка визначає – використовує
програма операції з плаваючою крапкою чи ні, виявляється
недостатньо, і програміст повинен зайвий раз викликати функцію,
використовує операції з плаваючою точкою, щоб змусити компілятор
включити підтримку таких операцій.

16. Інтерфейс з операційною системою.

16.1 Як прочитати з клавіатури один символ, не чекаючи нового рядка?

В: Всупереч популярному переконання і бажанням багатьох, це питання (як і
родинні питання, пов’язані з дублюванням символів) не відноситься
до мови С. Передача символів з “клавіатури” програмі, написаній на
С, здійснюється операційною системою, ця операція не
стандартизована мовою С. Деякі версії бібліотеки curses
містять функцію cbreak (), яка робить саме те, що потрібно.
Якщо Ви намагаєтеся прочитати пароль з клавіатури без виведення його на
екран, спробуйте getpass (). В операційній системі UNIX використовуйте
ioctl для зміни режиму роботи драйвера терміналу (CBREAK або RAW для
“Класичних” версій; ICANON, c_cc [VMIN] і с_сс [VTIME] для System V
або Posix). В системі MS-DOS використовуйте getch (). В системі VMS
спробуйте функції управління екраном (SMG $) або curses, або
використовуйте низькорівневі команди $ QIO з кодами IO $ _READVBLK (і,
може бути, IO $ M_NOECHO) для прийому одного символу за раз. В інших
операційних системах викручуйтеся самі. Пам’ятайте, що в деяких
операційних системах зробити щось подібне неможливо, так як
робота з символами здійснюється допоміжними процесорами і
не перебуває під контролем центрального процесора.

Питання, відповіді на які залежать від операційної системи,
недоречні в comp.lang.c. Відповіді на багато питань можна знайти в FAQ
таких груп як comp.unix.questions і comp.os.msdos.programmer.
Майте на увазі, що відповіді можуть відрізнятися навіть у разі різних
варіантів однієї і тієї ж операційної системи. Якщо питання стосується
специфіки операційної системи, пам’ятайте, що відповідь, придатний у Вашій
системі, може бути непотрібний всім іншим.

Дивись: PCS Розд. 10 c. 128-9, Розд. 10.1 c. 130-1.

16.2 Як визначити – чи є символи для читання (і якщо є, то скільки?)
І навпаки, як зробити, щоб виконання програми не блокувалося,
коли немає символів для читання?

В: Відповідь на ці питання також цілком залежить від операційної системи.
У деяких версіях curses є функція nodelay (). В залежності
від операційної системи Ви зможете використовувати “неблокуючим введення /
висновок “або системний виклик” select “або ioctl FIONREAD, або kbhit (),
або rdchk (), або опцію O_NDELAY функцій open () або fcntl ().

16.3 Як очистити екран? Як виводити на екран негативне зображення?

В: Це залежить від типу термінала (чи дисплея). Можете використовувати
таку бібліотеку як termcap або curses, або якісь інші
функциии, придатні для даної операційної системи.

16.4 Як дізнатися стан миші?

В: Подивіться в системній документації, або помістіть питання
(Попередньо подивившись їх FAQ) в одну з груп, які обговорюють
певну операційну систему. Робота з мишею абсолютно несхожа
в X window, MS-DOS, Macintosh, і, можливо, в будь-який інший
операційній системі.

16.5 Як програма може визначити повний шлях до місця, з якого вона
була викликана?

В: argv [0] може містити весь шлях, частина його або нічого не містити.
Якщо ім’я файлу в argv [0] є, але інформація не повна, можливо
повторення логіки пошуку виконуваного файлу, що використовується
інтерпретатором командного мови. Гарантованих або мобільних
рішень, однак, не існує.

16.6 Як процес може змінити змінну оточення батьківського
процесу?

В: Загалом, ніяк. Різні операційні системи забезпечують схожу з
UNIX можливість завдання пари ім’я / значення. Чи може програма з
користю для себе поміняти оточення, і якщо так, то як – все це
залежить від операційної системи.

В системі UNIX процес може модифікувати своє оточення
(У деяких системах є для цього функції setenv () та / або putenv ())
і модифіковане оточення зазвичай передається дочірнім процесам
але _не_ поширюється на батьківський процес.

16.7 Як перевірити, чи існує файл? Мені необхідно запитувати
користувача перед тим як переписувати існуючі файли.

В: В UNIX-подібних операційних системах можна спробувати функцію
access (), хоча є деякі проблеми. (Застосування access () може
позначитися на подальших діях, крім того, можливі особливості
виконання в setuid-програмах). Інше (можливо, краще) рішення
– Викликати stat (), вказавши ім’я файлу. Єдиний універсальний,
гарантує мобільність спосіб полягає в спробі відкрити файл.

16.8 Як визначити розмір файла до його читання?

В: Якщо “розмір файлу” – це кількість літер, яке можна прочитати,
то, взагалі кажучи, ця кількість заздалегідь невідомо. В операційній
системі Unix виклик функції stat дає точну відповідь, і багато
операційні системи підтримують схожу функцію, яка дає
приблизний відповідь. Можна c допомогою fseek переміститися в кінець
файлу, а потім викликати ftell, але такий прийом немобілен (дає точний
відповідь тільки в системі Unix, в інших же випадках відповідь майже точний
лише для певних стандартом ANSI “двійкових” файлів).
У деяких системах є підпрограми filesize або filelength.

І взагалі, чи так потрібно заздалегідь знати розмір файлу? Адже найточніший
спосіб визначення його розміру в С програмі полягає у відкритті та
читанні. Може бути, можна змінити програму так, що розмір файлу
буде отримано в процесі читання?

16.9 Як вкоротити файл без знищення або переписування?

В: В системах BSD є функція ftruncate (), кілька інших систем
підтримують chsize (), в деяких є (можливо,
недокументовані) параметр fcntl F_FREESP. В системі MS-DOS можна
іноді використовувати write (fd, “”, 0). Однак, повністю мобільного
рішення не існує.

16.10 Як реалізувати затримку або визначити час реакції користувача,
щоб похибка була менше секунди?

В: У цього завдання немає, на жаль, мобільних рішень. Unix V7 і її
похідні мали дуже корисну функцію ftime () c точністю до
мілісекунди, але вона зникла в System V і Posix. Пошукайте такі
функції: nap (), setitimer (), msleep (), usleep (), clock (), і
gettimeofday (). Виклики select () і poll () (якщо ці функції доступні)
можуть бути додані до сервісних функцій для створення простих
затримок. В системі MS-DOS можливо перепрограмування системного
таймера і переривань таймера.

16.11 Як прочитати об’єктний файл і передати управління на одну з його
функцій?

В: Необхідний динамічний компонувальник і / або завантажувач. Можливо виділити
пам’ять за допомогою malloc і читати об’єктні файли, але потрібні великі
пізнання в форматах об’єктних файлів, модифікації адрес і пр.
В системі BSD Unix можна використовувати system () і ld-A для
динамічної компоновки. Mного (більшість?) Версії SunOS та
System V мають бібліотеку-ldl, що дозволяє динамічно завантажувати
об’єктні модулі. Є ще GNU пакет, який називається “dld”.
Див також питання 7.6.

16.12 Як виконати з програми команду операційної системи?

В: Використовуйте system ().

Дивись: K & R II Розд. B6 c. 253; ANSI Розд. 4.10.4.5; H & S
Розд. 21.2; PCS Розд. 11 c. 179;

16.13 Як перехопити те, що видає команда операційної системи?

В: Unix і деякі інші операційні системи мають функцію popen (),
яка перепризначає потік stdio каналу, пов’язаного з процесом,
запустив команду, що дозволяє прочитати вихідні дані (або
передати вхідні). А можна просто (див. питання 16.12) перенаправити
вихід команди у файл, потім відкрити його і прочитати.

Дивись: PCS Розд. 11 c. 169.

16.14 Як отримати вміст директорія в С програмі?

В: З’ясуйте, чи не можна використовувати функції opendir () і readdir (),
доступні в більшості систем Unix. Реаліціі цих функцій відомі
для MS-DOS, VMS та інших систем. (MS-DOS має також функції
findfirst і findnext, які роблять в точності те ж саме).

16.15 Як працювати з послідовними (COM) портами?

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

17. Різне.

17.1 Що можна з упевненістю сказати про початкові значеннях змінних,
які явно не ініціалізовані? Якщо глобальні змінні
мають нульове початкове значення, то чи правильно нульове значення
присвоюється вказівниками і змінним з плаваючою точкою?

А: “Статичний” змінні (тобто оголошені поза функцій і ті, що
оголошені як належать класу stаtic) завжди ініціалізувалися
(Прямо при старті програми) нулем, як ніби програміст написав
“= 0”. Значить, змінні будуть ініціалізовані як нульові покажчики
(Відповідного типу; див. розділ 1), якщо вони оголошені покажчиками,
або значеннями 0.0, якщо були оголошені змінні з плаваючою крапкою.

Змінні автоматичного класу (тобто локальні змінні без
специфікації static), якщо вони явно не визначені, спочатку
містять “сміття”. Ніяких корисних передбачень щодо сміття
зробити не можна.

Пам’ять, динамічно виділяється з допомогою malloc і realloc також
буде містити сміття і повинна бути ініціалізований, якщо це
необхідно, викликає програмою. Пам’ять, виділена за допомогою
calloc, зануляют всі біти, що не завжди годиться для покажчиків або
змінних з плаваючою точкою (див. питання 3.13 і розділ 1).

17.2 Цей текст взятий прямо з книги, але він не компілюється.

  f()
  {
  char a[] = “Hello, world!”;
  }

В: Можливо, Ваш компілятор створений до прийняття стандарту ANSI і
ще не підтримує ініціалізацію “автоматичних агрегатів”
(Тобто нестатичні локальних масивів і структур).

Щоб викрутитися з цієї ситуації, зробіть масив статичним або
глобальним, або ініціалізує його за допомогою strcpy, коли
викликається f (). (Завжди можна ініціалізувати автоматичну
змінну char * стрінгів літер, але див. питання 17.20). Див також
питання 5.16, 5.17.

17.3 Як писати дані у файл, щоб їх можна було читати на машинах
з іншим розміром слова, порядком байтів або іншим форматом чисел
з плаваючою точкою?

В: Краще рішення – використовувати текстові файли (зазвичай ASCII),
c даними, записаними fprintf. Читати дані краще за все з
допомогою fscanf або чогось подібного. (Такий же рада застосуємо
для мережевих протоколів). До думок, що текстові файли занадто
великі й можуть довго оброблятися, ставитеся скептично.
Крім того, що ефективність таких операцій може бути на практиці
прийнятною, здатність маніпулювати даними за допомогою стандартних
коштів може мати вирішальне значення.

Якщо необхідно використовувати двійковий формат, переносимість даних
можна покращити (або отримати вигоду від використання готових
бібліотек введення / виводу), якщо використовувати стандартні формати даних,
такі як XDR (RFC 1014) (Sun), ASN.1 (OSI), X.409 (CCITT), або ISO
8825 “Основні правила кодування” Див також питання 9.11.

17.4 Як вставити або видалити рядок (або запис) в середині файлу?

В: Доведеться, мабуть, переписати файл. Див питання 16.9.

17.5 Як повернути з функції кілька значень?

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

17.6 Якщо є вказівник (char *) на ім’я функції у вигляді стринга, то як
цю функцію викликати?

В: Найбільш прямолінійний шлях – створення таблиці імен та відповідних
їм покажчиків:

  int function1(), function2();

  struct {char *name; int (*funcptr)(); } symtab[] =
  {
  “function1”,   function1,
  “function2”,   function2,
  };

Ну а тепер потрібно пошукати в таблиці потрібне ім’я і викликати функцію,
використовуючи пов’язаний з ім’ям покажчик. Див також питання 9.9 і 16.11.

17.7 У мене, здається, немає головного файлу . Надішліть мені його,
будь ласка.

В: Стандартні головні файли існують в тому сенсі, що містять
інформацію, необхідну компілятору, операційної системи і
процесору. “Чужий” головний файл підійде лише тоді, коли взято з
ідентичного оточення. Поцікавтеся у продавця компілятора, чому
відсутній головний файл, або попросіть надіслати новий натомість
втраченого.

17.8 Як викликати процедури, написані на мові FORTRAN (C + +, BASIC, Pascal,
Ada, Lisp) з С (і навпаки).

В: Відповідь повністю залежить від машини і від специфіки передачі параметрів
різними компіляторами. Рішення взагалі може не бути. Уважно
читайте керівництво по компілятору. Іноді в документації є
“Керівництво по змішаному програмування”, хоча техніка передачі
аргументів і забезпечення правильного входу у функцію найчастіше досить
таємнича. Додаткова інформація знаходиться в файлі FORT.gz
Глена Гершом, (Glenn Geers) який можна отримати за допомогою ftp
suphys.physics.su.oz.au в директорії src.

Головний файл cfortran.h спрощує взаємодію C / FORTRAN на багатьох
популярних машинах. cfortran.h можна отримає через ftp
zebra.desy.de (131.169.2.244).

В C + + модифікатор “C” зовнішньої функції показує, що функція буде
викликатися з використанням угоди про передачу параметрів мови
С.

17.9 Хто-небудь знає про програми, які переводять Pascal або FORTRAN
(Або LISP, Ada, awk, “старий” С) в С?

В: Є кілька загальнодоступних програм:

p2c Перекладач з Паскаля на С, написаний Дейвом Гіллеспі,
(Dave Gillespie) поміщений в comp.sources.unix в Березні 1990
(Volume 21); доступний також через ftp csvax.cs.caltech.edu,
файл pub/p2c-1.20.tar.Z.

ptoc Інший перекладач з Паскаля на С, написаний на Паскалі
(Comp.sources.unix, Volume 10, поправки в vol. 13?)

f2c Перекладач з Фортрану на С спільно розроблений
Bell Labs, Bellcore, and Carnegie Mellon. Подробиці
можна отримати, надіславши електронною поштою повідомлення
“Send index from f2c” за адресою netlib@research.att.com
або research! netlib.
(Ці подробиці можна отримати і через ftp
netlib.att.com, в директорії netlib/f2c.)

Укладач цього списку запитань і відповідей має список інших
комерційних трансляторів, серед них транслятори для менш відомих
мов. Див також питання 5.3.

17.10 Чи правда, що C + + – надмножество С. Чи можна використовувати
компілятор C + + для трансляції C програм?

В: З + + виріс із С і великою мірою базується на ньому, але деякі
правильні конструкції З неприпустимі в C + +. (Багато З програми,
будуть, тим не менш, правильно транслюватися компілятором С + +).

17.11 Мені потрібен: О: Шукай програми, які
називаються (див. також питання 17.12)

генератор перехресних cflow, calls, cscope
посилань З

C форматізатор cb, indent

17.12 Де знайти всі ці загальнодоступні програми?

В: Якщо у Вас є доступ до Usenet, дивіться періодично поміщаються
повідомлення в comp.sources.unix і comp.sources.misc, які описують
деякі деталі ведення архівів і підказують, як отримати ті
чи інші файли. Зазвичай використовується ftp і / або uucp c центральним,
орієнтованим на користувачів сервером, таким як uunet
(Ftp.uu.net, 192.48.96.9). Однак, в цих питаннях і відповідях
неможливо досліджувати або перерахувати всі архівні сервери і
розповісти про доступ до них.

Ай Ша (Ajay Shah) підтримує список загальнодоступних програм в
області чисельного аналізу, який періодично публікується,
і його можна знайти там же, де і дані питання та відповіді (див.
питання 17.33). Група Usenet comp.archives містить численні
оголошення про те, що є на різних ftp. Поштовий сервер
“Archie” може підказати, на якому ftp є ті чи інші програми.
Пошліть поштове повідомлення “help” за адресою
        archie@quiche.cs.mcgill.ca для отримання подальших інструкцій.
Нарешті, група comp.sources.wanted – зазвичай саме відповідне місце,
де можна розмістити відповідний запит, але подивіться перш _іх_
список питань і відповідей (FAQ) “Як знайти джерела”.

17.13 Де відбудуться наступні Змагання з Незрозуміло з
Програмування (International Obfuscated C Code Contest – IOCCC)?
Як отримати програми, які перемогли в поточному та минулих конкурсах?

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

{Apple, pyramid, sun, uunet}! Hoptoad! Judges або
judges@toad.com

, В розділі Subject якого напишіть “send rules”.
Майте на увазі, що це _не_ адресу, куди треба посилати конкурсні
програми.

Переможці конкурсу спочатку оголошуються на річної конференції
Usenix (Summer Usenix Conference) в середині червня і стають
доступними в мережі десь в липні-серпні. Програми-переможці
минулих конкурсів (починаючи з 1984 р.) архівовані в uunet (див.
питання 17.12) в директорії ~ / pub / ioccc.

В крайньому випадку програми-переможці минулих конкурсів можна
отримати, надіславши за вказаною вище адресою лист в графі Subject
якого потрібно вказати: “send YEAR winners”, де YEAR – рік,
представлений чотирма цифрами, інтервал у кілька років або “all”.

17.14 Чому неприпустимі вкладені коментарі? Як накажете
“Вимкнути” фрагмент програми, в якому вже є коментарі?
Чи можна використовувати коментарі всередині стрінгових констант?

В: Вкладені коментарі принесуть більше шкоди, ніж користі, головним
чином через можливість випадково не закрити коментар, залишивши
всередині нього символи “/ *”. З цієї причини краще “вимкнути” великої
фрагмент програми, в якому вже є коментарі, за допомогою засобів
препроцесора # ifdef або # if 0 (але майте на увазі питання 5.11).

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

Дивись: ANSI Appendix E p. 198, Rationale Розд. 3.1.9 p. 33.

17.15 Як отримати значення коду ASCII тієї чи іншої літери, і навпаки?

В: В С літери представлені цілими числами, відповідними їх значенням.
(Відповідно до набором символів даної машини). Так що немає
необхідності в перетворенні: якщо відома літера, то відомо
та її значення.

17.16 Як реалізувати послідовності та / або масиви біт?

В: Використовуйте масиви змінних типу char або int і кілька
макросів для операцій з окремими бітами (використовуйте визначення
8 для CHAR_BIT, якщо немає головного файлу :

# Include / * для CHAR_BIT * /

   #define BITMASK(bit) (1 << ((bit) % CHAR_BIT))
   #define BITSLOT(bit) ((bit) / CHAR_BIT)
   #define BITSET(ary, bit) ((ary)[BITSLOT(bit)] /= BITMASK(bit))
   #define BITTEST(ary, bit) ((ary)[BITSLOT(bit)] & BITMASK(bit))

17.17 Як найкращим чином визначити число встановлених біт,
відповідних певному значенню?

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

17.18 Як підвищити ефективність роботи програми?

В: Тема ефективності, дуже часто зачеплена в comp.lang.c,
не так важлива як багато хто схильний думати. Велика частина коду в
більшості програм не впливає на час виконання. Якщо час,
займане якимось ділянкою коду, мало в порівнянні із загальним
часом виконання, то для цієї ділянки набагато важливіше простота
і мобільність, ніж ефективність. (Пам’ятаєте, що комп’ютери дуже,
дуже швидкі і навіть “неефективний” ділянку коду може виконуватися
без видимої затримки).

Сумно відомі спроби передбачити “гарячі точки” програми.
Коли ефективність програми має значення, важливо використовувати
профіліровщики для визначення тих ділянок програми, які
заслуговують на увагу. Часто основний час виконання поглинається
периферійними операціями, такими як введення / виведення і виділення пам’яті,
які можна прискорити за допомогою буферизації і хешування.

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

Незграбні спроби оптимізації здатні так збільшити розмір
програми, що її ефективність впаде.

Подальше обговорення суперечностей, пов’язаних з ефективністю, а так
ж хороші поради щодо збільшення ефективності, коли це важливо,
дивіться в розділі 7 книги Керніган і Плоджера “Елементи стилю
програмування “, а також у книзі Джона Бентлі” Написання
ефективних програм “.

17.19 Чи правда, що застосування покажчиків більш ефективно, ніж
застосування масивів? Наскільки уповільнює програму виклик функції?
Швидше чи + + i ніж i = i + 1?

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

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

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

Перш ніж переписувати вирази типу i = i +1, згадайте, що маєте
справу з компілятором С а не з програмованим калькулятором. Будь
пристойний компілятор буде однаково транслювати + + i, i + = 1; i = i +1.
Використовувати + + i, i + = 1 або i = i +1 – питання стилю, не ефективності.
(Див. також питання 4.7).

Читати 6 частина

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*