EDIT: microtherion дає чудову відповідь, яка виправляє деякі мої моменти тут, зокрема щодо використання пам'яті.
Як ви визначили, існують певні ситуації, коли ви змушені використовувати a #define
, оскільки компілятор не дозволяє const
змінну. Так само в деяких ситуаціях ви змушені використовувати змінні, наприклад, коли вам потрібен масив значень (тобто ви не можете мати масив #define
).
Однак є багато інших ситуацій, коли не обов’язково є однієї «правильної» відповіді. Ось декілька вказівок, яких я б дотримувався:
Безпека типу
З загальної точки зору програмування const
змінні зазвичай є кращими (де це можливо). Основна причина цього - безпека типу.
#define
(Препроцесор макро) безпосередньо копіює буквене значення в кожне місце в коді, що робить кожен незалежно використання. Це може гіпотетично спричинити неоднозначності, оскільки тип може в кінцевому підсумку вирішуватися по-різному залежно від того, як / де він використовується.
const
Мінлива лише коли - або один тип, який визначається його декларації, і вирішені в ході ініціалізації. Він часто вимагає явного виступу, перш ніж він поводитиметься по-різному (хоча бувають різні ситуації, коли його можна сміливо рекламувати неявно). Як мінімум, компілятор може (якщо правильно налаштовано) видавати більш надійне попередження при виникненні проблеми з типом.
Можливе вирішення цього питання - включити чіткий склад або суфікс типу в #define
. Наприклад:
#define THE_ANSWER (int8_t)42
#define NOT_QUITE_PI 3.14f
Такий підхід потенційно може спричинити проблеми із синтаксисом, але залежно від способу його використання.
Використання пам’яті
На відміну від обчислювальної техніки загального призначення, пам'ять, очевидно, має перевагу при роботі з чимось на зразок Arduino. Використання const
змінної та a #define
може вплинути на збереження даних у пам'яті, що може змусити вас використовувати те чи інше.
const
змінні (як правило) будуть зберігатися в SRAM разом з усіма іншими змінними.
- Буквальні значення, які використовуються в
#define
, часто зберігатимуться в програмному просторі (флеш-пам’яті) поряд із самим ескізом.
(Зауважте, що існують різні речі, які можуть точно впливати на те, як і де зберігається щось, наприклад конфігурація компілятора та оптимізація.)
SRAM та Flash мають різні обмеження (наприклад, 2 UB та 32 KB для Uno відповідно). У деяких додатках SRAM досить легко закінчитися, тому може бути корисно перекласти деякі речі у Flash. Можливий і зворотний, хоча, мабуть, менш поширений.
ПРОГМЕМА
Можна отримати переваги безпеки типу, зберігаючи дані в програмному просторі (Flash). Це робиться за допомогою PROGMEM
ключового слова. Він працює не для всіх типів, але зазвичай використовується для масивів цілих чисел або рядків.
Загальна форма, наведена в документації , така:
dataType variableName[] PROGMEM = {dataInt0, dataInt1, dataInt3...};
Таблиці рядків трохи складніше, але в документації є повні деталі.