Я предпочту, чтобы константы определили?

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

46
задан Thom Wiggers 26 July 2015 в 22:41
поделиться

10 ответов

Нет, в общем случае вы не должны использовать объекты с уточненными константами в 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 работает на вас, т.е. он делает то, что вы от него хотите, он действительно превосходит макросы во многих отношениях, поскольку имеет область видимости и типизирован. Вероятно, вам следует предпочесть такие объекты, где это применимо, однако в общем случае вам придется принимать во внимание указанные выше ограничения.

101
ответ дан 26 November 2019 в 20:07
поделиться

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

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

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

10
ответ дан 26 November 2019 в 20:07
поделиться

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

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

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

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

5
ответ дан 26 November 2019 в 20:07
поделиться

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

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

2
ответ дан 26 November 2019 в 20:07
поделиться

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

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

  • директива switch
  • подстановка в исходную строку
  • макросы кода

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

#define VERSION 4
...

#if VERSION==4
   ................
#endif 
3
ответ дан 26 November 2019 в 20:07
поделиться

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

1
ответ дан 26 November 2019 в 20:07
поделиться

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

DEFINES легко определять и использовать из файлов заголовков (.h), где любой опытный программист на C мог бы ожидать, что он найдет определенные константы. Определить константы в файлах заголовков не так просто - требуется больше кода, чтобы избежать дублирования определений и т. Д.

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

1
ответ дан 26 November 2019 в 20:07
поделиться

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

Вы можете выполнять проверки во время компиляции, чтобы убедиться, что макрос находится в допустимом диапазоне (и #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 как макрос на каком-то уровне оптимизации.

1
ответ дан 26 November 2019 в 20:07
поделиться

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

const int A=12;
switch (argc) {
    case A:
    break;
}
7
ответ дан 26 November 2019 в 20:07
поделиться

Хотя этот вопрос специфичен для 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 ++.

6
ответ дан 26 November 2019 в 20:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: