Muitos programas de baixo nível usam a palavra-chave volátil para tipos de mapeamento de memória e coisas do tipo, no entanto, estou meio confuso sobre o que REALMENTE faz em segundo plano. Em outras palavras, o que significa quando o compilador não "otimiza" o endereço de memória?
9
volatile
variável e diz 5, e você lê-lo novamente no próximo ano, você está garantido para obter 6.Respostas:
volatile
significa que algum outro processador ou dispositivo de E / S ou algo pode alterar a variável de baixo de você.Com uma variável comum, as etapas do seu programa são a única coisa que irá alterá-lo. Por exemplo, se você ler
5
uma variável e não a alterar, ela ainda conterá5
. Como você pode confiar nisso, seu programa não precisa gastar tempo para ler a variável novamente na próxima vez que você quiser usá-la. O compilador C ++ é inteligente para gerar código que apenas se lembra do5
.Mas você pode ler como
5
, então talvez o sistema carregue dados do disco na memória, alterando-os para500
. Se você deseja que seu programa leia o valor novo500
, é necessário que o compilador não seja muito inteligente sobre o uso da leitura anterior5
. Você precisa dizer a ele para recarregar o valor toda vez. Isso é o quevolatile
faz.Uma analogia para crianças de 5 anos
Digamos que você coloque uma grande folha de papel em uma mesa. Em um canto do papel, você anota a pontuação atual de um jogo em andamento
3 to 4
,. Então você vai para o lado oposto da mesa e começa a escrever uma história sobre o jogo. Seu amigo que está assistindo o jogo atualiza a pontuação naquele canto à medida que o jogo avança. Ela apaga3 to 4
e escreve3 to 5
.Quando você coloca a pontuação do jogo em sua história, você pode:
3 to 4
assumindo alegremente que não mudou (ou não se importando se mudou) ou3 to 5
agora é a atual) e volte. É assim que umavolatile
variável age.fonte
volatile
significa duas coisas:O valor da variável pode mudar sem que nenhum código seu a altere. Portanto, sempre que o compilador lê o valor da variável, ele não pode assumir que é o mesmo da última vez que foi lido ou que é o mesmo que o último valor armazenado, mas deve ser lido novamente.
O ato de armazenar um valor em uma variável volátil é um "efeito colateral" que pode ser observado de fora; portanto, o compilador não tem permissão para remover o ato de armazenar um valor; por exemplo, se dois valores são armazenados em uma linha, o compilador deve realmente armazenar o valor duas vezes.
Como um exemplo:
O compilador deve armazenar o número dois, ler a variável i, armazenar a variável em que leu.
Existe outra situação: se uma função usa
setjmp
e depoislongjmp
é chamada, é garantido que todas as variáveis locais voláteis da função tenham o último valor armazenado - esse não é o caso de variáveis locais não voláteis.fonte
i
e o valorpi = &i
,x = *pi
a leitura será feitai
, mas não é garantido que essa leitura tenha semântica volátil.i
é declarado comovolatile int i
entãopi
deve ser declarado comovolatile int *pi
, nesse caso,*pi
é um acesso volátil, não?Explicação abstrata
C e C ++ têm o conceito de uma máquina abstrata . Quando o código usa o valor de alguma variável, a máquina abstrata diz que a implementação precisa acessar o valor dessa variável. O código do formulário
statement_A; statement_B; statement_C;
deve ser executado exatamente na ordem especificada. Expressões comuns a essas três instruções devem ser recalculadas sempre que ocorrerem.Pelas máquinas abstratas, dada a sequência de instruções
statement_A; statement_B; statement_C;
, a implementação deve primeiro executarstatement_A
em sua totalidade, depoisstatement_B
e finalmentestatement_C
. A implementação não se lembra de que você atribuiuage
o valor 5. Toda declaração que referenciaage
deve acessar o valor dessa variável.Não haveria necessidade da
volatile
palavra - chave se as implementações executassem estritamente o código C ou C ++ de acordo com as especificações abstratas da máquina. As máquinas abstratas C e C ++ não têm conceito de registradores, subexpressões comuns e a ordem de execução é rigorosa.Ambos os idiomas também têm regras como se . Uma implementação é compatível com o padrão desde que ela se comporte como se tivesse executado coisas de acordo com a especificação abstrata da máquina. O compilador pode assumir que variáveis não voláteis não alteram valores entre atribuições. Desde que não quebre a
as-if
regra, a sequênciastatement_A; statement_B; statement_C;
pode ser implementada executando parte destatement_C
, depois parte destatement_A
, depois todostatement_B
, depois o restantestatement_A
e, finalmente, o restantestatement_C
.Essas regras como se não se aplicam a
volatile
variáveis. No que diz respeito àsvolatile
variáveis e funções, uma implementação precisa fazer exatamente o que você pediu e exatamente na ordem em que você disse para fazer as coisas.Há uma desvantagem na especificação abstrata da máquina: é lenta. Um aspecto positivo de C e C ++ em comparação com outras linguagens é que elas são bastante rápidas. Este não seria o caso se o código fosse executado por essas máquinas abstratas. Os COMO SE regras são o que permitirá C e C ++ para ser tão rápido.
Resposta ELI5
"Otimizar" um endereço de memória é um conceito avançado, algo que não se enquadra nas capacidades de uma criança de cinco anos. As crianças de cinco anos em conformidade farão exatamente o que você manda, nem mais nem menos. Com
volatile
, você está dizendo à implementação para agir como se fosse cinco: sem pensar, sem otimizações sofisticadas. Em vez disso, a implementação precisa fazer exatamente o que o código diz.fonte
(non-) volatile é uma dica para o compilador como otimizar o código (do ponto de vista do código de montagem gerado):
fonte
As respostas parecem bastante consistentes, mas faltam um ponto importante. Você está dizendo ao compilador que deseja alocar espaço e, para cada acesso, leia OR WRITE, deseja que ele execute esse acesso. Não queremos que ele otimize esses acessos ou essa variável por algum motivo.
Sim, uma razão é porque outra pessoa pode alterar esse valor para nós. Outro motivo é que podemos estar alterando esse valor para outra pessoa. Que outra pessoa, que a modifique para nós ou para a qual estamos modificando, pode ser hardware / lógica ou software. É frequentemente usado para definir acessos para controle e registros de status em programas embarcados bare metal, gravando ou lendo no hardware. Bem como o software conversando com o software explicado em outras respostas.
Você também verá o volátil usado para controlar quando e em que ordem os acessos ocorrem, se você estiver tentando cronometrar uma seção do código e não usar voláteis as variáveis em questão (horário de início, horário de término e diferença). computado próximo ao final, o compilador é livre para mover qualquer uma das medições de tempo (e não onde as colocamos), não que ele não seja volátil, mas a experiência mostra menos probabilidade.
Na ocasião, você verá que ele costumava queimar tempo, um pisca-pisca elementar, o olá mundo do bare metal, pode usar um volátil para uma variável que conta com um grande número apenas para queimar tempo para o olho humano ver o led mudar estado. Exemplos mais avançados que o uso de temporizadores ou outros eventos para queimar o tempo.
fonte