Чи використовувати макроси C / C ++ як ярлик для умовної компіляції є хорошою практикою?


13

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

Зазвичай мені доведеться написати щось подібне

#ifdef DEBUG
    std::cout << "Debug message" << std::endl;
#endif

що досить громіздко і дратівливо використовувати у багатьох місцях.

Чи є хорошою практикою визначити макрос для фрагмента коду, щоб ви використовували його таким чином?

MSG_DEBUG("Debug message")

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



З питання не зрозуміло, чому б ви не просто поставили умовний код у функцію і викликали це. Чи є якісь інші обмеження, які б заважали цьому?
Олексій

@gnat Питання, про яке ви згадали, настільки широке, що більшість людей не пов'язують його з цією темою, особливо коли вони шукають це конкретне питання в Інтернеті.
Еноку

3
Ваше запитання позначено як c, так і c ++ , однак це досить різні мови. Чи можете ви уточнити, про кого ви говорите? Ваш приклад був би абсолютно чудовим на C, але, можливо, він буде краще реалізований, наприклад, constexpr ifу C ++.
Йорг W Міттаг

1
Як сторону, діагностика повинна йти STDERR. Крім того, чому б не зробити це залежним від того, NDEBUGяк assert()це робить замість цього? Тоді ви можете визначити це як те #define DEBUG_MSG(MSG) assert(std::cerr << MSG), що тестує стан потоку теж.
Дедуплікатор

Відповіді:


19

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

Чи варто взагалі використовувати макроси? На мій погляд, ви повинні, оскільки це прийнята практика в C, і будь-яке рішення, що не потребують макросів, вимагало б принаймні чогось виконувати навіть поза режимом налагодження. Типовий програміст C в будь-який час вибере трохи некрасивий макрос над зайвими зусиллями.


13

Тут є елемент особистих уподобань, але в C ++ я вважаю за краще це робити у файлі заголовка:

#ifdef _DEBUG
    void DebugMessage(...);
#else
    inline void DebugMessage(...) {}
#endif

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

Очевидно, вам також потрібно включити відповідне визначення функції у .cppфайлі в #ifdef _DEBUGблоці.


Але накладні виклики все ще присутні тут, чи не так?
Еноку

7
Якщо ваш компілятор генерує код для виклику відомої порожньої функції у складанні випуску, перше і найбільше, що вам потрібно зробити для підвищення ефективності, - це набагато кращий компілятор. Це дійсно тривіальна оптимізація.
Девід Торнлі

@Eenoku Ні, як каже Девід, його буде видалено будь-яким компілятором, який ви повинні використовувати.
Джек Едлі

3
Тут є ключова відмінність: макрос (залежно від того, як він написаний) не оцінював би його вирази аргументів, тоді як функція завжди буде. Крім того, невизначена поведінка передавати нетривіальні аргументи функціям varargs (і зазвичай спрацьовує попередження компілятора).
Себастьян Редл


2

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.