Определение константных значений в C

голоса
4

У меня есть C проект , где весь код организован в *.c/ *.hпар файлов, и мне нужно определить постоянное значение в одном файле, который будет , однако , также можно использовать в других файлах. Как я должен объявить и определить это значение?

Должен ли он быть static const ...в *.hфайле? Как extern const ...в *.hфайле и определены в *.cфайле? Каким образом это имеет значение , если значение не является примитивным типом данных ( int, doubleи т.д.), но char *или struct? (Хотя в моем случае это double.)

Определение материала внутри *.hфайлов не кажется хорошей идеей в целом; один должен объявить вещи в *.hфайле, но определить их в *.cфайле. Тем не менее, extern const ...подход представляется неэффективным, так как компилятор не сможет встраивать значение, то вместо того , чтобы получить доступ через его адрес все время.

Я предполагаю , что суть этого вопроса: Если один определить static const ...значения в *.hфайлах C, для того , чтобы использовать их в более чем одном месте?

Задан 10/12/2008 в 07:16
источник пользователем
На других языках...                            


10 ответов

голоса
8

Правило я следовать, чтобы объявить только вещи в H-файлов и определить их в файлах C. Вы можете объявить и определить в одном файле C, предполагая, что он будет использоваться только в этом файле.

По декларации, я имею в виду уведомить компилятор о его существовании , но не выделить место для него. Это включает в себя #define, typedef, extern int xи так далее.

Определения присваивают значение деклараций и выделить место для них, таких как int xи const int x. Это включает в себя определение функций; включая их в заголовочных файлах часто приводит к растрате кода пространства.

Я видел слишком много младших программистов запутаться , когда они положили const int x = 7;в файл заголовок , а затем удивляются , почему они получают ошибку ссылки для xопределяются более одного раза. Я думаю , что , как минимум, вам нужно static const int x, чтобы избежать этой проблемы.

Я бы не слишком беспокоиться о скорости кода. Основная проблема с компьютерами (с точки зрения скорости и стоимости) давно перешли от скорости выполнения для облегчения разработки.

Ответил 10/12/2008 в 07:46
источник пользователем

голоса
3

Если вам нужны константы (реальная, компилировать постоянные времени), вы можете сделать это тремя способами, помещая их в файлы заголовков (нет ничего плохого с этим):

enum {
    FOO_SIZE = 1234,
    BAR_SIZE = 5678
};

#define FOO_SIZE 1234
#define BAR_SIZE 5678

static const int FOO_SIZE = 1234;
static const int BAR_SIZE = 5678;

В C ++, я предпочитаю использовать перечислимую путь, так как она может быть ограничена в пространстве имен. Для C, я использовать макрос. Это basicially сводится к тому, дело вкуса, хотя. Если вам нужно константы с плавающей точкой, вы не можете использовать перечисление больше. В C ++ я использовать последний путь, статический сопз двойной, в этом случае (примечание в C ++ статики будет излишним, то они стали бы статичным автоматически, так как они Const). В C, я бы продолжать использовать макросы.

Это миф , что с помощью третьего метода будет замедлять вашу программу в любом случае. Я предпочитаю перечисление , так как значения вы получаете являются rvalues - вы не можете получить свой адрес, который я расценить в качестве дополнительной безопасности. Кроме того, существует гораздо меньше шаблонный код , написанный. Глаз сосредоточен на постоянных.

Ответил 11/12/2008 в 00:14
источник пользователем

голоса
1

Как правило, вы не определяют вещи , как staticв заголовке. Если вы определите staticпеременные в заголовке, каждый файл , который использует заголовок получает свою собственную копию любой декларируются static, что является противоположностью DRY принципа: не повторять себя .

Таким образом, вы должны использовать альтернативу. Для целочисленных типов, используя перечисление (определенное в заголовке) является очень мощным; он хорошо работает с отладчиками тоже (хотя лучше отладчики могут быть в состоянии помочь с #defineмакро - значениями тоже). Для нецелых типов, externдекларация (необязательно квалифицированы const) в заголовке и одно определение в одном файле C, как правило, лучший способ пойти.

Ответил 10/12/2008 в 08:53
источник пользователем

голоса
1

Есть ли у вас действительно есть необходимость беспокоиться о преимуществе инлайн? Если вы не пишете встроенный код, придерживайтесь читаемости. Если это действительно магическое число чего - то, я бы использовать определение; Я думаю , что Const лучше для таких вещей как константная версии строк и модифицирующих аргументы вызова функции. Тем не менее , определить в .c, объявить в .h правила, безусловно , достаточно общепринятые конвенции, и я бы не разбить его только потому , что вы могли бы сохранить поиск памяти.

Ответил 10/12/2008 в 08:28
источник пользователем

голоса
0

В C ++, вы всегда должны использовать

const int SOME_CONST = 17;

для постоянных и никогда

#define SOME_CONST 17

Определяет, почти всегда будет возвращаться и укусить вас позже. Consts в языке, и сильно типизированных, так что вы не получите странные ошибки из-за какого-то скрытого взаимодействия. Я бы поставил сопзЬ в соответствующем файле заголовка. Пока это #pragma один раз (или #ifndef х / #define х / #endif), вы никогда не будете получать какой-либо ошибки компиляции.

В ванильным C, вы можете иметь проблемы совместимости, где вы должны использовать #defines.

Ответил 11/12/2008 в 01:40
источник пользователем

голоса
0

Для того, чтобы ответить на суть вашего вопроса:
Вы , как правило , НЕ требуется определить статическую переменную в файле заголовка.
Это заставит вас иметь дублированные переменные в каждом перевод единицах (C - файлы) , которые включают в себя заголовок.

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

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

Ответил 10/12/2008 в 13:36
источник пользователем

голоса
0

для AUTOCONF среды: Вы всегда можете определить константы в файле конфигурирования, а также. AC_DEFINE () я предполагаю, что макрос для определения по всей сборке.

Ответил 10/12/2008 в 09:26
источник пользователем

голоса
0

Я хотел бы видеть больше контекста для вашего вопроса. Тип значения имеет решающее значение, но вы оставили его. Смысл константного ключевого слова в C является довольно тонким; например , Const символ * р; не означает , что указатель р является постоянной; Вы можете написать р все , что вам нравится. То , что вы не можете писать это память , что р указывает на, и это остается верным даже при изменении значений р в. Речь идет о единственном случае , я действительно понимаю; в общем, смысл тонкого размещения сопзЬ ускользает от меня. Но это особый случай является чрезвычайно полезным для параметров функции , потому что он извлекает обещание от функции , что память на аргумент указывает на не будет мутировал.

Существует еще один частный случай должен знать каждый: целые числа. Почти всегда, постоянные, называемые целые числа должны быть определены в файле .h как литералы перечисления . Типы перечислений не только позволяют вам константы , связанные групп вместе естественным образом, но и позволят вам имена этих констант можно увидеть в отладчике, что является огромным преимуществом.

Я написал десятки тысяч строк C; вероятно, сотни, если я пытаюсь отслеживать его вниз. (Туалет ~ / SRC / с / *. С говорит 85 тысяч, но некоторые, что генерируется, и, конечно, есть много C кода, скрывающегося в другом месте). Помимо двух дел о, я никогда не находил много пользы для Уст. Я был бы рад, чтобы узнать новый, полезный пример.

Ответил 10/12/2008 в 07:29
источник пользователем

голоса
0

Я могу дать вам косвенный ответ. В C ++ (в отличие от C) constподразумевает static. Деятельности Банка сказать в C ++ static constэто то же самое , как const. Так что говорит вам , как это стандарты C ++ тело чувствует о проблеме т.е. все consts должны быть статичными.

Ответил 10/12/2008 в 07:26
источник пользователем

голоса
-1

Если вы хотите , чтобы встраивать значение в ваших функциях вы должны использовать #define MY_MAGIC_NUMBER 0x12345678
Даже static const unsigned MY_MAGIC_NUMBER = 0x12345678вызовет извлекающее значение из адреса. Штраф производительность не будет действительно важно , если вам значение много в петлях.
Я использую только constдля аргументов функции.

Был несколько комментариев и вниз голосов по поводу этого ответа , так я проверил мое предположение и рассматривать сгенерированную сборку и этот ответ неверен. В принципе , #defineи constдаст тот же результат.

Ответил 10/12/2008 в 07:43
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more