Должен ли я использовать константы над определениями?

В C, предпочитаю ли я константы над определениями? В последнее время я читаю много кода, и все примеры сильно используют определения.

Нет, в общем случае вы не должны использовать объекты const, созданные в C, для создания констант имен. Чтобы создать именованную константу в C, вы должны использовать либо macros ( #define ), либо enums. На самом деле, язык C не имеет констант, в том смысле, что вы, кажется, подразумеваете. (C в этом отношении существенно отличается от C ++)

В языке C понятия постоянного и постоянного выражения определяются очень иначе, чем C ++. В константе C подразумевается буквальное значение , например 123 . Вот несколько примеров констант в C

 123 34.58 'x' 

Константы в C могут использоваться для создания постоянных выражений . Однако, поскольку объекты const любого типа не являются константами в C, они не могут использоваться в постоянных выражениях и, следовательно, вы не можете использовать объекты с константой, в которых требуются постоянные выражения.

Например, следующее не является константой

 const int C = 123; /* C is not a constant!!! */ 

и поскольку приведенное выше C не является константой, оно не может использоваться для объявления типа массива в области файла

 typedef int TArray[C]; /* ERROR: constant expression required */ 

Он не может использоваться как ярлык для случая

 switch (i) { case C: ; /* ERROR: constant expression required */ } 

Он не может использоваться в качестве ширины битового поля

 struct S { int f : C; /* ERROR: constant expression required */ }; 

Он не может использоваться в качестве инициализатора для объекта со статической продолжительностью хранения

 static int i = C; /* ERROR: constant expression required */ 

Он не может использоваться в качестве инициализатора enums

 enum { E = C /* ERROR: constant expression required */ }; 

т.е. он не может использоваться везде, где требуется постоянная .

Это может показаться контр-интуитивным, но это как C язык определен.

Вот почему вы видите эти многочисленные #define -s в коде, с которым работаете. Опять же, на языке C объект, имеющий const, имеет очень ограниченное использование. Они в основном совершенно бесполезны, как «константы», поэтому на языке C вы в основном вынуждены использовать #define или enums для объявления истинных констант.

Разумеется, в ситуациях, когда для вас работает объект const-qual, т. Е. Он делает то, что вы хотите, он действительно превосходит macros по-разному, поскольку он ограничен и типизирован. Вероятно, вам следует предпочесть такие объекты, где это применимо, однако в общем случае вам придется учитывать вышеуказанные ограничения.

Константы должны быть предпочтительнее define s. Существует несколько преимуществ:

  • Тип безопасности . В то время как C является слабо типизированным языком, использование define теряет всю безопасность типа, что позволит компилятору подобрать проблемы для вас.

  • Простота отладки . Вы можете изменить значение констант через отладчик, в то время как define s автоматически изменяется в коде препроцессором на фактическое значение, а это означает, что если вы хотите изменить значение для целей тестирования / отладки, компиляции.

Может быть, я использовал их неправильно, но, по крайней мере, в gcc, вы не можете использовать константы в операторах case.

 const int A=12; switch (argc) { case A: break; } 

Хотя этот вопрос специфичен для C, я думаю, это хорошо знать об этом:

 #include int main() { const int CON = 123; int* A = &CON; (*A)++; printf("%d\n", CON); // 124 in C } 

работает в C , но не в C ++

Одна из причин использования #define заключается в том, чтобы избежать таких вещей, чтобы испортить ваш код, особенно это сочетание C и C ++.

Многие люди здесь дают вам совет «C ++ style». Некоторые даже говорят, что аргументы C ++ применимы к C. Это может быть справедливым моментом. (Является ли это или нет чувствует себя субъективным.) Люди, которые говорят, что const иногда означает, что что-то другое на двух языках также правильное.

Но это в основном незначительные моменты и лично, я думаю, что в действительности есть относительно незначительные последствия для любого пути. Это вопрос стиля, и я думаю, что разные группы людей дадут вам разные ответы.

С точки зрения общего использования, исторического использования и наиболее распространенного стиля, в C, гораздо более типично видеть #define . Использование C ++-isms в C-коде может быть столь же странным для некоторого узкого сегмента C-кодеров. (В том числе и меня, так что там лежат мои предубеждения).

Но я удивлен, что никто не предложил решение средней точки, которое «чувствует себя правильно» на обоих языках: если оно вписывается в группу целочисленных констант, используйте enum .

define может использоваться для многих целей (очень свободно), и его следует избегать, если вы можете заменить его на const, который определяет переменную, и вы можете сделать с ней намного больше.

В таких случаях, как указано ниже, следует использовать определение

  • директивный переключатель
  • подстановка в исходную строку
  • macros кода

Пример, когда вы должны использовать define over const, – это когда у вас есть номер версии 3, и вы хотите, чтобы версия 4 включала некоторые методы, недоступные в версии 3

 #define VERSION 4 ... #if VERSION==4 ................ #endif 

Определения были частью языка дольше, чем константы, поэтому многие старые коды будут использовать их, потому что определяет, где единственный способ выполнить работу, когда код был написан. Для более позднего кода это может быть просто вопрос программиста.

Константы имеют тип, а также значение, поэтому они предпочли бы, когда имеет смысл для вашего значения иметь тип, но не тогда, когда он является бесприбыльным (или полиморфным).

Если это не определено программно, я использую #define . Например, если я хочу, чтобы все мои объекты UI имели одинаковое пространство между ними, я мог бы использовать #define kGUISpace 20 .

Помимо превосходных причин, которые AndreyT использует для использования DEFINES, а не констант в коде «C», существует еще одна прагматическая причина использования DEFINES.

ОПРЕДЕЛЕНИЯ – это легкое определение и использование файлов заголовков (.h), в которых любой опытный C-кодер будет искать найденные константы. Определение consts в файлах заголовков не так просто – его больше кода, чтобы избежать дублирования определений и т. Д.

Кроме того, аргументы «typafe» являются спорными, большинство компиляторов будут воспринимать вопиющие ошибки, такие как получение строки и int, или «сделают правильную вещь» при небольшом рассогласовании, таком как присвоение целочисленного значения float.

Макросы (определения) могут использоваться препроцессором и во время компиляции константы не могут.

Вы можете выполнять проверки времени компиляции, чтобы убедиться, что макрос находится в допустимом диапазоне (и #error или #fatal, если это не так). Вы можете использовать значения по умолчанию для макроса, если они еще не определены. Вы можете использовать макрос в размере массива.

Компилятор может оптимизировать с помощью макросов лучше, чем может, с помощью констант:

 const int SIZE_A = 15; #define SIZE_B 15 for (i = 0; i < SIZE_A + 1; ++i); // if not optimized may load A and add 1 on each pass for (i = 0; i < SIZE_B + 1; ++i); // compiler will replace "SIZE_B + 1" with 16 

Большая часть моей работы связана со встроенными процессорами, у которых нет потрясающих оптимизационных компиляторов. Возможно, gcc будет рассматривать SIZE_A как макрос на определенном уровне оптимизации.

  • изменение значения переменной const в C ++
  • Предоставляет ли C ++ 11 вектор ?
  • постоянный указатель vs указатель на постоянное значение
  • когда использовать const и const ссылку в функции args
  • Как удалить дублирование кода между аналогичными функциями const и non-const?
  • Объявить массив const
  • Почему строковые литералы const?
  • Легкое правило для чтения сложных объявлений const?
  • Каковы используются константные указатели (в отличие от указателей на объекты const)?
  • Почему кто-то использует #define для определения констант?
  • Как преобразовать «указатель на тип указателя» в const?
  • Interesting Posts

    Увеличить размер кучи в Java

    jenkins + сонар + интеграция github

    Eclipse CDT с использованием MinGW не выводится в консоли

    Невозможно изменить ArrayAdapter в ListView: UnsupportedOperationException

    Как загрузить файл из папки ресурсов?

    Лучший алгоритм для согласования цветов.

    Какой алгоритм для игры tic-tac-toe можно использовать для определения «лучшего движения» для ИИ?

    Использование горячих клавиш VLC через командную строку

    Резюме: сделайте снимок с использованием намерения камеры и отобразите фотографию с правильной ориентацией (работает, надеюсь, на все устройства)

    Злая двойная проблема и субтрактивное слияние

    Установка Windows XP на внешний жесткий диск?

    Как добавить движущие эффекты к моим элементам управления на C #?

    В чем разница между типом (myVar) и (типом) myVar?

    Перегрузка оператора индексирования индексов индексирования C ++ таким образом, чтобы можно было отвечать на обновления

    Вложенная функция в C

    Давайте будем гением компьютера.