Есть несколько различных способов определения символьных констант в C:
- Использование препроцессора:
#define FOO something
- Использование констант перечисления:
enum { FOO=1, BAR=10, BLETCH=100 };
- Использование константных переменных:
const double PI=3.14159265359;
У каждого есть свои «за» и «против».
препроцессор макросы в основном только текст замена, и могут быть использованы для простых значений:
#define FOO 10
#define STR "This is a test"
#define PI 3.14159265359
или для более сложных выражений
#define BAR (FOO * PI + BLETCH)
Проблема заключается в том, что препроцессор макросы заменяются во время предварительной обработки этап, поэтому после компиляции кода символы FOO
, STR
, PI
и BAR
больше не существуют (что может затруднить отладку на уровне сборки) , и они не подчиняются правилам определения области видимости (т. е. если вы создаете макрос внутри функции, то видимость не ограничивается только этой функцией, она будет видна любому коду, следующему определению функции).
Вы можете использовать константы перечисления для целочисленных значений:
enum { FOO = 1, BAR = 10, BLETCH = 100 };
Они не будут заменены после предварительной обработки, поэтому они видны в отладчики. Значения известны во время компиляции, поэтому их можно использовать для размеров массивов или случаев в операциях switch
. Константы перечисления занимают пространство имен с именами переменных и функций, поэтому вы не можете использовать один и тот же символ для константы перечисления и переменной. Константы перечисления do соответствуют правилам определения; если вы определяете тип enum
внутри функции, эти константы перечисления не будут видны вне тела функции.
Вы не можете использовать константы перечисления для значений не int
(строки, поплавки, любое целое значение, превышающее int
).
Вы можете использовать const
-qualified переменные:
const double PI = 3.14159265359;
const char * const STR = "This is a string constant";
const int FOO = 10;
Почти гибкими, как макросы препроцессора, символы не заменяются препроцессором. Как и константы перечисления, переменные подчиняются правилам определения области. Недостатком является то, что хранилище должно быть выделено для всех этих объектов во время выполнения, и они не считаются compile-time константами, то есть они не могут использоваться для таких вещей, как случаи в операторе switch
.
Ни одна схема не всегда «лучше»; это действительно зависит от того, что вам нужно.
Со своей стороны, я использую метод enum
для взаимосвязанных целочисленных констант (коды ошибок, состояния машин и т. Д.) И const
-qualified переменные для почти всего остального. Я редко использую макросы препроцессора для символических констант.
'объявляет 1 и 0 как FALSE и TRUE', почему бы не использовать C99' '? –
Какая версия C (C89, C99, C11) поддерживает ваш код? – alk
'// объявляет 1 и 0 как FALSE и TRUE' сбивает с толку, так как упорядочение предлагает' FALSE' '' '' '' '' '' '' '' '' '' ''! Кроме того, я просто определял бы «FALSE» как «0», а не с помощью «! TRUE», который, вероятно, должен иметь круглые скобки для обеспечения безопасности. –