2016-04-20 2 views
1

Я действительно использую что-то подобное, чтобы сделать константы для моей функции ошибки. Является ли это прекрасным, или я должен делать это как-то иначе?Какое правильное объявление констант в C?

// declares 1 and 0 as a FALSE and TRUE 
#define TRUE 1 
#define FALSE !TRUE 

// declares "error types" 
const enum { 
    SYNTAX = 0, 
    ZERO_OPERATOR = 1, 
    ZERO_MINUS = 2 
}; 

Как я использую "типы ошибок" константы в коде:

If (!something) error(SYNTAX); // there is a switch in error function which prints the error 
+5

'объявляет 1 и 0 как FALSE и TRUE', почему бы не использовать C99' '? –

+1

Какая версия C (C89, C99, C11) поддерживает ваш код? – alk

+3

'// объявляет 1 и 0 как FALSE и TRUE' сбивает с толку, так как упорядочение предлагает' FALSE' '' '' '' '' '' '' '' '' '' ''! Кроме того, я просто определял бы «FALSE» как «0», а не с помощью «! TRUE», который, вероятно, должен иметь круглые скобки для обеспечения безопасности. –

ответ

2

Есть несколько различных способов определения символьных констант в 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 переменные для почти всего остального. Я редко использую макросы препроцессора для символических констант.

Смежные вопросы