Скажем, у меня есть функция
int foo(int * const bar){
while(!*bar){
printf("qwertyuiop\n");
}
}
где я намерен изменить значение в bar
на что-то отличное от 0, чтобы остановить этот цикл. Было бы уместно вместо этого написать это, как показано ниже?
int foo(int volatile * const bar){
while(!*bar){
printf("qwertyuiop\n");
}
}
volatile
не для многопоточности. Если другой поток изменяет значение, вам нужен atomic
.
volatile
был предназначен для таких вещей, как регистры устройства с отображением памяти, где указываемое значение могло «волшебным образом» измениться «за спиной компилятора» из-за характера задействованного оборудования. Предполагая, что вы не пишете код, который имеет дело со специальным оборудованием, которое может «спонтанно» изменить значение, на которое указывает bar
, тогда вам не нужно (и не следует) использовать ключевое слово volatile
. Простого пропуска ключевого слова const
достаточно, чтобы компилятор (и любой программист, который может вызвать функцию) знал, что указанное значение может быть изменено.
Обратите внимание: если вы собираетесь установить *bar
из другой темы, то ключевое слово volatile
не достаточно хорошо; даже если вы пометите указатель как volatile, компилятор все равно не гарантирует правильную обработку. Чтобы этот вариант использования работал правильно, вам нужно либо синхронизировать все операции чтения и записи в *bar
с помощью мьютекса, либо, альтернативно, использовать std::atomic<int>
вместо простого int
.
Согласованный; однако const T * bar
будет функционировать как обещание, что foo()
не изменит значение int
, на которое указывает bar
. (это только обещание, а не гарантия, потому что достаточно хитрый программист все еще может изменить bar
внутри foo()
, используя const_cast
, но мы будем считать здесь честной игрой :))
@FrançoisAndrieux Это было моим намерением. Указатель, который имеет foo()
, не изменяется, но изменяется значение в этом месте.
"где я намерен изменить значение": Что именно это означает? Как меняется значение?