В C я предпочту, чтобы константы определили? У меня есть чтение большого количества кода в последнее время, и все примеры делают интенсивное использование, определяет.
Нет, в общем случае вы не должны использовать объекты с уточненными константами в C для создания констант имен. Чтобы создать именованную константу в C, вы должны использовать либо макросы ( #define
), либо перечисления. Фактически, язык C не имеет констант в том смысле, который вы, кажется, подразумеваете. (C существенно отличается от C ++ в этом отношении)
В языке C понятия константы и константного выражения очень отличаются от C ++. В C константа означает буквальное значение , например 123
. Вот несколько примеров констант в C
123
34.58
'x'
Константы в C могут использоваться для построения константных выражений . Однако, поскольку константные объекты любого типа не являются константами в C, они не могут использоваться в константных выражениях, и, следовательно, вы не можете использовать константные объекты, где требуются константные выражения.
Например, следующее не является константой
const int C = 123; /* C is not a constant!!! */
, и поскольку указанный выше C
не является константой, его нельзя использовать для объявления типа массива в области файла
typedef int TArray[C]; /* ERROR: constant expression required */
Его нельзя использовать как метка case
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 */
Не может использоваться в качестве инициализатора перечисления
enum {
E = C /* ERROR: constant expression required */
};
, т.е. использоваться везде, где требуется константа .
Это может показаться нелогичным, но именно так определяется язык C.
Вот почему вы видите эти многочисленные #define
-вы в коде, с которым вы работаете. Опять же, в языке C объекты с квалификацией const используются очень ограниченно. Они в основном совершенно бесполезны как «константы», поэтому в языке C вы в основном вынуждены использовать #define
или перечисления для объявления истинных констант.
Конечно, в ситуациях, когда объект с квалификацией const работает на вас, т.е. он делает то, что вы от него хотите, он действительно превосходит макросы во многих отношениях, поскольку имеет область видимости и типизирован. Вероятно, вам следует предпочесть такие объекты, где это применимо, однако в общем случае вам придется принимать во внимание указанные выше ограничения.
Константы должны быть предпочтительнее, чем define
s. Есть несколько преимуществ:
Типовая безопасность . В то время как C является слабо типизированным языком, использование define
теряет всю безопасность типов, что позволяет компилятору решать проблемы за вас.
Простота отладки . Вы можете изменить значение констант через отладчик, в то время как define
автоматически изменяются в коде препроцессором на фактическое значение , что означает, что если вы хотите изменить значение для целей тестирования / отладки, вам необходимо перекомпилировать.
Многие здесь дают вам советы по "стилю C ++". Некоторые даже говорят, что аргументы C ++ применимы к C. Это может быть справедливым аргументом. (Независимо от того, кажется ли это субъективным.) Люди, которые говорят const
, иногда имеют в виду что-то другое на двух языках, также правы.
Но это в основном второстепенные моменты, и лично я думаю, что на самом деле у любого пути есть относительно незначительные последствия. Это вопрос стиля, и я думаю, что разные группы людей дадут вам разные ответы.
С точки зрения общего использования, исторического использования и наиболее распространенного стиля в C гораздо более типично видеть #define
. Использование измов C ++ в коде C может показаться странным для определенного узкого сегмента программистов C. (Включая меня, так что именно в этом и заключаются мои предубеждения.)
Но я удивлен, что никто не предложил золотое решение, которое "кажется правильным" на обоих языках: если оно входит в группу целочисленных констант, используйте перечисление
.
Определения были частью языка дольше, чем константы, поэтому многие старые программы будут использовать их, потому что определения были единственным способом выполнить работу, когда код был написан. Для более нового кода это может быть просто вопросом привычки программиста.
Константы имеют тип, так же как и значение, поэтому их лучше использовать, когда значение имеет смысл иметь тип, но не когда оно не имеет типа (или полиморфно).
define может использоваться для многих целей (очень свободно), и его следует избегать, если вы можете заменить его на const, который определяет переменную, и вы можете сделать намного больше с этим.
В случаях, как показано ниже, необходимо использовать определение
Пример, где вы должны использовать определение вместо константы, - это когда у вас есть номер версии скажем 3, и вы хотите, чтобы версия 4 включала некоторые методы, которые недоступны в версии 3
#define VERSION 4
...
#if VERSION==4
................
#endif
Если это что-то, что не определяется программно, я использую #define
. Например, если я хочу, чтобы все мои объекты пользовательского интерфейса имели одинаковое пространство между собой, я могу использовать #define kGUISpace 20
.
Помимо веских причин, приведенных AndreyT в пользу использования DEFINES вместо констант в коде "C", есть еще одна, более прагматическая причина для использования DEFINES.
DEFINES легко определять и использовать из файлов заголовков (.h), где любой опытный программист на C мог бы ожидать, что он найдет определенные константы. Определить константы в файлах заголовков не так просто - требуется больше кода, чтобы избежать дублирования определений и т. Д.
Также "типизированные" аргументы спорны, большинство компиляторов обнаружат вопиющие ошибки, такие как присвоение строки и int, или, будет «делать правильные вещи» при небольшом несоответствии, таком как присвоение целого числа с плавающей запятой.
Макросы (определения) могут использоваться препроцессором, а во время компиляции константы не могут.
Вы можете выполнять проверки во время компиляции, чтобы убедиться, что макрос находится в допустимом диапазоне (и #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 как макрос на каком-то уровне оптимизации.
Возможно, я использовал их неправильно, но, по крайней мере в gcc, вы не можете использовать константы в операторах case.
const int A=12;
switch (argc) {
case A:
break;
}
Хотя этот вопрос специфичен для C, я думаю, это полезно знать :
#include<stdio.h>
int main() {
const int CON = 123;
int* A = &CON;
(*A)++;
printf("%d\n", CON); // 124 in C
}
работает в C , но не в C ++
Одна из причин использовать #define
- избегать таких вещей, которые могут испортить ваш код, особенно это смесь C и C ++.