Diferença entre const & const volatile

90

Se declararmos uma variável como volatilesempre que o valor fresco for atualizado
Se declararmos uma variável como constentão o valor dessa variável não será alterado

Então, const volatile int temp;
qual é a utilidade de declarar a variável tempcomo acima?
O que acontece se declararmos como const int temp?

user559208
fonte
Você não usaria const volatile int temp;no escopo do bloco (ou seja, dentro { }), não tem uso lá.
MM de

Respostas:

149

Um objeto marcado como const volatilenão terá permissão para ser alterado pelo código (um erro será gerado devido ao constqualificador) - pelo menos por meio desse nome / ponteiro específico.

A volatileparte do qualificador significa que o compilador não pode otimizar ou reordenar o acesso ao objeto.

Em um sistema embarcado, isso é normalmente usado para acessar registros de hardware que podem ser lidos e atualizados pelo hardware, mas não fazem sentido para gravar (ou pode ser um erro para gravar).

Um exemplo pode ser o registro de status para uma porta serial. Vários bits irão indicar se um caractere está esperando para ser lido ou se o registrador de transmissão está pronto para aceitar um novo caractere (isto é, - está vazio). Cada leitura desse registro de status pode resultar em um valor diferente dependendo do que mais ocorreu no hardware da porta serial.

Não faz sentido escrever no registro de status (dependendo da especificação de hardware em particular), mas você precisa se certificar de que cada leitura do registro resulta em uma leitura real do hardware - usando um valor em cache de uma leitura anterior. t informá-lo sobre as mudanças no estado do hardware.

Um exemplo rápido:

Se esses ponteiros não foram marcados como sendo volatile, alguns problemas podem ocorrer:

  • o teste do loop while pode ler o registrador de status apenas uma vez, já que o compilador pode assumir que o que quer que seja apontado nunca mudará (não há nada no teste do loop while ou no próprio loop que possa alterá-lo). Se você entrou na função quando não havia nenhum caractere esperando no hardware UART, você pode terminar em um loop infinito que nunca parou mesmo quando um caractere foi recebido.
  • a leitura do registrador de recebimento pode ser movida pelo compilador para antes do loop while - novamente, porque não há nada na função que indique que *recv_regé alterado pelo loop, não há razão para que não possa ser lido antes de entrar no loop.

Os volatilequalificadores garantem que essas otimizações não sejam realizadas pelo compilador.

Michael Burr
fonte
5
1 para explicação. E eu tenho uma pergunta: e quanto aos métodos voláteis Const? Se eu tiver uma classe, que é acessada por muitos threads (embora o acesso seja sincronizado com mutex), meus métodos const também devem ser voláteis (já que alguma variável pode ser alterada por outro thread)
Sasa
41
  • volatile dirá ao compilador para não otimizar o código relacionado à variável, geralmente quando sabemos que ela pode ser alterada "de fora", por exemplo, por outro thread.
  • const dirá ao compilador que é proibido para o programa modificar o valor da variável.
  • const volatileé uma coisa muito especial que você provavelmente verá usado exatamente 0 vezes em sua vida (tm). Como era de se esperar, isso significa que o programa não pode modificar o valor da variável, mas o valor pode ser modificado de fora, portanto, nenhuma otimização será realizada na variável.
mingos
fonte
12
Eu pensei que volatilevariáveis ​​geralmente são o que acontece quando você começa a mexer com o hardware, não com outros threads. Eu vi o const volatileuso em coisas como registradores de status mapeados em memória ou semelhantes.
APENAS MINHA OPINIÃO correta
2
Claro, você está absolutamente certo, multithreading é apenas um exemplo, mas não o único :).
mingos
26
Se você trabalha com sistemas embarcados, verá isso com muita frequência.
Daniel Grillo
29

Não é porque a variável é const que ela pode não ter mudado entre dois pontos de sequência.

Constância é uma promessa que você faz de não alterar o valor, não de que o valor não será alterado.

Alexandre C.
fonte
10
Mais um para apontar que os constdados não são "constantes".
Bogdan Alexandru
7

Precisei usar isso em um aplicativo incorporado onde algumas variáveis ​​de configuração estão localizadas em uma área da memória flash que pode ser atualizada por um carregador de boot. Essas variáveis ​​de configuração são 'constantes' durante o tempo de execução, mas sem o qualificador volátil, o compilador otimizaria algo assim ...

... pré-computando o valor da constante e usando uma instrução de montagem imediata ou carregando a constante de um local próximo, de modo que quaisquer atualizações do valor CANID original na área de configuração do flash sejam ignoradas. CANID tem que ser constantemente volátil.

push2eject
fonte
7

Em C, conste volatilesão qualificadores de tipo e esses dois são independentes.

Basicamente, constsignifica que o valor não pode ser modificado pelo programa.

E volatilesignifica que o valor está sujeito a alterações repentinas (possivelmente de fora do programa).

Na verdade, o Padrão C dá um exemplo de uma declaração válida que é conste volatile. O exemplo é:

extern const volatile int real_time_clock;

onde real_time_clockpode ser modificável pelo hardware, mas não pode ser atribuído, incrementado ou decrementado.

Portanto, já devemos tratar conste volatileseparadamente. Estes qualificadores tipo pode ser aplicado a struct, union, enume typedefcomo bem.

user2903536
fonte
5

constsignifica que a variável não pode ser modificada pelo código c, não que ela não pode ser alterada. Isso significa que nenhuma instrução pode escrever na variável, mas seu valor ainda pode mudar.

volatilesignifica que a variável pode mudar a qualquer momento e, portanto, nenhum valor armazenado em cache pode ser usado; cada acesso à variável deve ser executado em seu endereço de memória.

Uma vez que a pergunta está marcada como "incorporada" e supondo que tempseja uma variável declarada pelo usuário, não um registro relacionado ao hardware (já que geralmente são tratados em um arquivo .h separado), considere:

Um processador embutido que tem memória de dados de leitura e gravação volátil (RAM) e memória de dados somente leitura não volátil, por exemplo, memória FLASH na arquitetura de von-Neumann, onde dados e espaço de programa compartilham um barramento de dados e endereço comum.

Se você declarar const tempter um valor (pelo menos se diferente de 0), o compilador irá atribuir a variável a um endereço no espaço FLASH, pois mesmo que tenha sido atribuído a um endereço RAM, ainda precisa de memória FLASH para armazenar o valor inicial da variável, tornando o endereço de RAM uma perda de espaço, uma vez que todas as operações são somente leitura.

Em consequência:

int temp;é uma variável armazenada na RAM, inicializada em 0 na inicialização (cstart), os valores em cache podem ser usados.

const int temp;é uma variável armazenada em (somente leitura) FLASH, inicializada em 0 no momento do compilador, os valores em cache podem ser usados.

volatile int temp; é uma variável armazenada na RAM, inicializada em 0 na inicialização (cstart), os valores em cache NÃO serão usados.

const volatile int temp; é uma variável armazenada em (somente leitura) FLASH, inicializada em 0 no momento do compilador, os valores em cache NÃO serão usados

Aí vem a parte útil:

Atualmente, a maioria dos processadores Embedded tem a capacidade de fazer alterações em sua memória não volátil somente leitura por meio de um módulo de função especial, que const int temppode ser alterado em tempo de execução, embora não diretamente. Dito de outra forma, uma função pode modificar o valor no endereço onde tempestá armazenado.

Um exemplo prático seria usar tempo número de série do dispositivo. A primeira vez que o processador embutido rodar, tempserá igual a 0 (ou o valor declarado) e uma função pode usar este fato para rodar um teste durante a produção e se for bem sucedido, pedir para ser atribuído um número de série e modificar o valor de temppor meio de uma função especial. Alguns processadores têm uma faixa de endereço especial com memória OTP (programável de uma só vez) apenas para isso.

Mas aí vem a diferença:

Se const int tempfor um ID modificável em vez de um número de série programável uma vez e NÃO for declarado volatile, um valor em cache pode ser usado até a próxima inicialização, o que significa que o novo ID pode não ser válido até a próxima reinicialização ou, pior ainda, algumas funções pode usar o novo valor enquanto outros podem usar um valor armazenado em cache mais antigo até a reinicialização. Se for const int tempdeclarado voltaile, a mudança de ID terá efeito imediato.

Michael Kusch
fonte
Uau, essa resposta é longa
5

Você pode usar conste volatilejuntos. Por exemplo, se 0x30for considerado o valor de uma porta que é alterada apenas por condições externas, a seguinte declaração evitaria qualquer possibilidade de efeitos colaterais acidentais:

Degrau
fonte
2

Em termos simples, o valor na variável 'const volatile' não pode ser modificado programaticamente, mas pode ser modificado pelo hardware. Volátil aqui é para evitar qualquer otimização do compilador.

rajeshsam
fonte
1

Usamos a palavra-chave 'const' para uma variável quando não queremos que o programa a altere. Ao passo que, quando declaramos uma variável 'const volatile', estamos dizendo ao programa para não alterá-la e ao compilador que essa variável pode ser alterada inesperadamente a partir de entradas vindas do mundo externo.

Todos
fonte