Що стосується багатьох питань, то відповідь на це питання - це залежить . Замість того, щоб сказати, що краще, я скоріше наводив приклади та цілі, коли один кращий за інших.
Як препроцесор, так і константа мають свої місця відповідного використання.
У випадку попереднього процесора код видаляється до часу компіляції. Отже, він найкраще підходить для ситуацій, коли очікується, що код не буде складений . Це може вплинути на структуру модуля, залежності, і це може дозволити вибір найкращих сегментів коду для аспектів продуктивності. У наступних випадках потрібно розділити код лише за допомогою препроцесора.
Багатоплатформний код:
Наприклад, коли код компілюється на різних платформах, коли код залежить від конкретних номерів версій ОС (або навіть версії компілятора - хоча це дуже рідко). Наприклад, коли ви маєте справу з малопомітними аналогами великих ендієнів коду - вони повинні бути відокремлені з препроцесорами, а не константами. Або якщо ви збираєте код для Windows, а також Linux, а певні системні дзвінки дуже різні.
Експериментальні виправлення: ще
один випадок, коли це має бути виправданим, є якийсь експериментальний код, який є ризиковим, або певні основні модулі, які потрібно опустити, які матимуть значні зв'язки або різницю в продуктивності. Причина, через яку можна було б відключити код за допомогою препроцесора, а не ховатися під if () , тому що ми можемо не бути впевнені в помилках, введених цим специфічним набором змін, і ми працюємо в експериментальній основі. Якщо це не вдається, ми не повинні робити нічого іншого, крім відключення цього коду у виробництві, ніж переписати. Деякий час ідеально використовувати #if 0 для коментування всього коду.
Справа із залежностями:
Ще одна причина, з якої ви можете сформувати Наприклад, якщо ви не хочете підтримувати зображення JPEG, ви можете допомогти позбутися від компіляції цього модуля / заглушки, і в кінцевому підсумку бібліотека не буде (статично чи динамічно) посилатися на це модуль. Іноді пакети запускаються ./configureдля ідентифікації доступності такої залежності, і якщо бібліотеки відсутні (або користувач не хоче включати), така функціональність відключається автоматично, не пов'язуючи її з цією бібліотекою. Тут завжди вигідно, якщо ці директиви генеруються автоматично.
Ліцензування:
Одним з дуже цікавих прикладів директиви препроцесора є ffmpeg . Він має кодеки, які потенційно можуть порушувати патенти при його використанні. Якщо ви завантажите джерело і компілюєте для встановлення, він запитає, чи хочете ви або не тримаєте подалі такі речі. Зберігання кодів прихованих за певних умов, якщо умови все-таки можуть стати вами в суді!
Копіювати-вставити код:
макроси Aka. Це не порада надмірно використовувати макроси - просто такі макроси мають набагато більш потужний спосіб застосувати еквівалент копіювання минулого . Але використовуйте його з великою обережністю; і використовуйте його, якщо ви знаєте, що ви робите. Константи, звичайно, не можуть цього зробити. Але можна використовувати і inlineфункції, якщо це легко зробити.
То коли ви використовуєте константи?
Майже скрізь.
Охайний потік коду:
загалом, коли ви використовуєте константи, він майже не відрізняється від звичайних змінних, а значить, краще читати код. Якщо ви пишете процедуру, що становить 75 рядків, після 3-х рядків через 3 і 4 рядки з #ifdef ДУЖЕ не вдається прочитати . Ймовірно, дається первинна константа, якою керує #ifdef, і використовувати її в природному потоці скрізь.
Добре відступний код: Вся директива щодо препроцесора ніколи не працює добре з інакше добре відрезаним кодом . Навіть якщо ваш компілятор дозволяє відступити #def, препроцесор Pre-ANSI C не дав місця між початком рядка та символом "#"; провідний "#" завжди повинен був бути розміщений у першій колонці.
Конфігурація:
Ще одна причина, через яку константи / або змінні мають сенс, полягає в тому, що вони можуть легко розвиватися від того, щоб бути пов'язаними з глобальними глобалами, або в майбутньому можуть бути розширені, щоб отримати від файлів конфігурації.
Одна остання річ:
ніколи не використовуйте директиви препроцесора #ifdefдля #endif
перетину сфери або { ... }. тобто початок #ifdefабо кінець з #endifрізних сторін { ... }. Це надзвичайно погано; це може заплутати, може бути десь небезпечно.
Це, звичайно, не є вичерпним переліком, але показує вам велику різницю, де метод більш сприятливий для використання. Справа не в тому, що краще , це завжди більше того, хто з них природніше використовувати в даному контексті.