Когда и для каких целей следует использовать ключевое слово const в C для переменных?
https://softwareengineering.stackexchange.com/questions/204500
-
29-09-2020 - |
Вопрос
Пока получаешь мой код рассмотрен здесь проблема использования const
появилось ключевое слово.Я понимаю, что он используется для реализации поведения переменных только для чтения.
Я в замешательстве относительно различных ситуаций, когда это может быть полезно.
- Следует ли его использовать для большей ясности в прототипах функций?
- Следует ли это использовать в качестве меры безопасности при разработке кода?
- Должен ли он использоваться в рамках различных функций для объявления констант времени выполнения?
- Стоит ли его вообще использовать?
Эти вопросы - всего лишь примеры путаницы, с которой я сталкиваюсь.Общая путаница заключается в следующем
- Когда должен быть
const
ключевое слово, используемое в программировании на языке Си? - Каковы различные виды преимуществ, которые можно получить, используя это ключевое слово в C?
- Есть ли какие-либо минусы в использовании
const
ключевое слово?
Было указано, что этот вопрос может быть слишком широким из-за всех этих вопросов, подробно изложенных в моем вопросе.Я просто хотел уточнить, что эти вопросы предназначены только для того, чтобы прояснить путаницу, связанную с основным вопросом.
Когда и для каких целей следует использовать ключевое слово const в C для переменных?
Это также можно перефразировать следующим образом
Правильное использование
const
ключевое слово в C` с одинаковыми плюсами и минусами.
Решение
При просмотре кода я применяю следующие правила:
Всегда используйте
const
для параметров функции, передаваемых по ссылке, когда функция не изменяет (или не освобождает) данные, на которые указано.int find(const int *data, size_t size, int value);
Всегда используйте
const
для констант, которые в противном случае могли бы быть определены с помощью #define или enum.В результате компилятор может найти данные в памяти, доступной только для чтения (ROM) (хотя компоновщик часто является лучшим инструментом для этой цели во встроенных системах).const double PI = 3.14;
Никогда не используйте const в функции прототип для параметра, переданного значение.Это не имеет никакого значения и, следовательно, является просто "шумом".
// don't add const to 'value' or 'size' int find(const int *data, size_t size, int value);
Там, где это уместно, используйте
const volatile
в местоположениях, которые не могут быть изменены программой, но все еще могут измениться.Типичным вариантом использования здесь являются аппаратные регистры, например регистр состояния, который отражает состояние устройства:const volatile int32_t *DEVICE_STATUS = (int32_t*) 0x100;
Другие виды использования необязательны.Например, параметры функции внутри функции реализация может быть помечен как const.
// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)
{
... etc
или функция возвращает значения или вычисления, которые были получены и затем никогда не изменялись:
char *repeat_str(const char *str, size_t n)
{
const size_t len = strlen(str);
const size_t buf_size = 1 + (len * n);
char *buf = malloc(buf_size);
...
Эти виды использования const
просто укажите, что вы не будете изменять переменную;они не меняют то, как и где хранится переменная.Компилятор, конечно, может вычислить, что переменная не изменяется, но путем добавления const
вы позволяете ему обеспечивать это.Это может помочь читателю и добавить некоторую безопасность (хотя, если ваши функции велики или
достаточно сложны, чтобы это имело большое значение, у вас, возможно, есть другие
проблемы). Редактировать - например.плотно закодированная функция из 200 строк с вложенными циклами и множеством длинных
или похожих имен переменных, знание того, что определенные переменные никогда не меняются, может
значительно облегчить понимание.Такие функции были плохо спроектированы или
обслуживались.
Проблемы с const
.Вероятно, вы услышите термин "постоянное отравление".Это происходит при добавлении const
к параметру функции приводит к распространению 'constness'
.
Редактировать - постоянное отравление:например, в функции:
int function_a(char * str, int n)
{
...
function_b(str);
...
}
если мы изменимся str
Для const
, затем мы должны обеспечить , чтобы fuction_b
также требуется
a const
.И так далее , если function_b
передает str
далее по function_c
,
и т.д.Как вы можете себе представить, это может быть болезненно, если оно распространяется на множество
отдельных файлов / модулей.Если он распространяется на функцию, которая не может быть
изменена (например, системную библиотеку), тогда становится необходимым приведение.Так что разбрызгивание
const
что-то в существующем коде, возможно, напрашивается на неприятности.В новом коде
однако, лучше всего const
проходите постоянную квалификацию там, где это уместно.
Более коварная проблема const
заключается в том, что это было не на языке оригинала
.В качестве дополнения это не совсем подходит.Для начала это имеет два значения
(как и в правилах выше, означает "Я не собираюсь это менять" и "это не может быть изменено").Но более того, это может быть опасно.Например, скомпилируйте и
запустите этот код, и (в зависимости от компилятора / опций) он вполне может аварийно завершиться при
запуске:
const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';
strchr
возвращает char*
ни один const char*
.В качестве параметра его вызова используется
const
это должно отлитый параметр вызова для char*
.И в этом случае это
отбрасывает реальное свойство хранилища, доступное только для чтения. Редактировать:- обычно это относится к переменным в памяти, доступной только для чтения.Под "ПЗУ" я подразумеваю не только физическое ПЗУ, но и любую память, защищенную от записи, как это происходит с разделом кода программ, запускаемых в обычной ОС.
Многие стандартные библиотечные функции ведут себя точно так же, так что будьте осторожны:когда у вас есть реальный константы (т.е.хранятся в ПЗУ), вы должны быть очень осторожны, чтобы не потерять их постоянство.
Другие советы
Generally in any programming language its recommended to use const
or the equivalent modifier since
- It can clarify to the caller that what they passed in is not going to change
- Potential speed improvements since the compiler knows for certain it can omit certain things that are only relevant if the parameter can change
- Protection from yourself accidentally changing the value
In agreement with TheLQ's statements:
When working with a team of programmers declaring const
is a good way of indicating that said variable shouldn't be modified, or just for reminding yourself in large projects. It's useful in that sense, and can save many headaches.
Yes, it's basically the TheLQ's answer.
Is a security measure for the programmer so you don't modify a variable, and to not call functions that may modify them. In an array or structure the const specifier indicates that the values of their contents won't be modified, and even the compiler will not allow you to do so. You still can easily change the value of the variable with just a cast however.
In what I have usually see, it's mostly used to add constant values in code, and to indicate that the array or structure won't be modified if you call a particular function. This last part is important, because when you call a function that WILL modify your array or structure, you may want to keep the original version, so you create a copy of the variable and then pass it to function. If that is not the case, you don't require the copy, obviously, so for example you can change,
int foo(Structure s);
to
int foo(const Structure * s);
and not getting the copy overhead.
Just to add, note that C has particular rules with the const specifier. For example,
int b = 1;
const int * a = &b;
is not the same as
int b = 1;
int * const a = &b;
The first code won't allow you to modify a. In the second case, the pointer is constant but its contents is not, so the compiler will allow you to say * a = 3;
without a compiler error, but you can't make a
to be a reference to another thing.