Volatile — ключевое слово языков C/C++, которое информирует компилятор о том, что значение переменной может меняться из вне и что компилятор не будет оптимизировать эту переменную. Примерно такое описание volatile я встречал во многих книгах и туториалах, и каждый раз мне не удавалось понять что же хотел сказать автор. На понимание этого я потратил n-ое количество времени, и вот специально для этого, чтобы упростить жизнь новичкам в понимании этого аспекта, решил написать как раз таки эту статью.
Оптимизация кода компилятором
«компилятор не будет оптимизировать эту переменную» — что означает оптимизировать? Наверное очень много людей, когда только начинали программировать задавались этим вопросом, не так ли? Думаю лучше продемонстрировать все на примерах, нежели рассказывать термины, которые большинству останутся не понятными.
Ну давайте начнем, к примеру имеем простой массив(правда не с простым размером), в цикле с которым выполняем какое-либо действие:
int ar[1024];
for(size_t i = 0; i < 1024; i++)
{
ar[i] = ...;
}
Самая затратная операция в этом примере не присваивание ячейке массива какого-либо значения и не инкремент счетчика, а именно операция сравнения, поэтому компилятор оптимизирует это примерно вот так:
int ar[1024];
for(size_t i = 0; i < 1024 / 4; i += 4)
{
ar[i] = ...;
ar[i + 1] = ...;
ar[i + 2] = ...;
ar[i + 3] = ...;
}
Еще очень простой пример, в котором имеем массив символов, с помощью цикла проходим по всей строке и выполняем какие-то действия с символами:
сhar str[125];
for(size_t i = 0; i < strlen(str); i++)
{
...
}
В этом случае компилятор вынесет вызов strlen() в отдельную переменную:
сhar str[125];
size_t length = strlen(str);
for(size_t i = 0; i < lenght; i++)
{
...
}
Также чтобы не писать код, так как он очевиден, компилятор заменяет умножение на 2, сложением, но и пожалуй самый главный пример по нашей тематике, это то, что в большинстве случаев компилятор разгружает runtime программы, путем подстановки в выражения уже их значения, к примеру мы пишем программу для лифта. Одно из условий данной программы таково, что как только зайдут к примеру больше 4 человек должно выдаться предупреждение.
const MAX_COUNT_PEOPLE = 4;
size_t countPeole = 0;
...
if(countPeople > MAX_COUNT_PEOPLE)
{
// Выдаем предупреждение
}
// Значение переменной countPeople к примеру будет менять с другого потока
Все же хорошо, ошибки невозможны в этом коде. Но по сути условие будет всегда истинно, так как компилятор уже запомнил значения этих переменных. И вот как раз таки в таких случаях применяется ключевое слово volatile, чтобы избежать подобных казусов, это будет выглядеть вот так:
const MAX_COUNT_PEOPLE = 4;
volatile size_t countPeole = 0;
...
if(countPeople > MAX_COUNT_PEOPLE)
{
// Выдаем предупреждение
}
// Значение переменной countPeople к примеру будет менять с другого потока
Заключение
Думаю мне получилось объяснить самые азы того зачем нужен volatile. Для еще лучшего понимания советую прочитать эту статью. Желаю удачи в изучение огромного мира технологий C/C++.
Автор: мастер слога