По-перше, я виявив, що неможливо визначити тип константи за допомогою #define, чому це?
Чому це що? Це неправда:
#define MY_INT_CONSTANT ((int) 12345)
По-друге, чи є якісь переваги використання одного з них перед іншим?
Так. #define
визначає макрос, який замінюється ще до початку компіляції. const
просто модифікує змінну, щоб компілятор позначив помилку, якщо ви спробуєте її змінити. Є контексти, в яких ти можеш використовувати a, #define
але ти не можеш використовувати a const
(хоча я намагаюся знайти його, використовуючи останній дзвін). Теоретично a const
займає місце у виконуваному файлі та вимагає посилання на пам'ять, але на практиці це незначно і може бути оптимізовано компілятором.
const
s набагато зручніші для компілятора та налагоджувача, ніж #define
s. У більшості випадків це найважливіший момент, який слід враховувати, приймаючи рішення, який із них використовувати.
Просто подумав про контекст, в якому ти можеш використовувати, #define
але ні const
. Якщо у вас є константа, яку ви хочете використовувати у безлічі .c
файлів, #define
просто додайте її в шапку. З a const
ви повинні мати визначення у файлі C та
const int MY_INT_CONST = 12345;
extern const int MY_INT_CONST;
у заголовку. MY_INT_CONST
не може використовуватися як розмір статичного або глобального масиву області в будь-якому файлі C, крім того, у якому він визначений.
Однак для цілочисельних констант можна використовувати enum
. Насправді це те, що Apple робить майже незмінно. Це має всі переваги і #define
s, і const
s, але працює лише для цілочисельних констант.
enum
{
MY_INT_CONST = 12345,
};
Нарешті, який шлях є більш ефективним та / або більш безпечним?
#define
є більш ефективним в теорії, хоча, як я вже говорив, сучасні компілятори, ймовірно, впевнені, що різниці мало. #define
є більш безпечним, оскільки завжди намагається призначити йому помилку компілятора
#define FOO 5
FOO = 6;
const
s можна обдурити, щоб їх було призначено, хоча компілятор може видавати попередження:
const int FOO = 5;
(int) FOO = 6;
Залежно від платформи, призначення може все-таки провалитися під час виконання, якщо константа розміщується в сегменті лише для читання, і це офіційно невизначена поведінка відповідно до стандарту C.
Особисто для цілочисельних констант я завжди використовую enum
s для констант інших типів, const
якщо не маю поважних причин цього не робити.