Pergunta

Eu tenho usado uma variável global estática e uma variável volátil estática no escopo do arquivo,

ambos são atualizados por um ISR e um loop principal e principais verificações de loop o valor da variável.

aqui durante a otimização nem a variável global, nem a variável volátil são otimizados. Então, ao invés de usar uma variável volátil uma variável global resolve o problema.

Então, é bom usar variável global em vez de volátil?

Você tem algum motivo específico para usar volátil estática ??

Qualquer programa exemplo seria apreciável.

Agradecemos antecipadamente ..

Foi útil?

Solução

São coisas diferentes. Eu não sou um especialista em semântica voláteis. Mas eu acho que faz sentido o que está descrito aqui.

Global

Global significa apenas o identificador em questão é declarada no arquivo escopo. Existem diferentes âmbitos, chamado de função (onde goto-rótulos são definidos no), fi le (onde globals residem), bloco (onde as variáveis ??locais normais residem), e protótipo da função (onde residem os parâmetros de função). Este conceito existe apenas para estruturar a visibilidade dos identificadores. Ele não tem nada a ver com otimizações.

estática

static é uma duração de armazenamento (não vamos olhar para isso aqui) e uma maneira de dar um nome declarado dentro ligação interna escopo do arquivo. Isso pode ser feito para funções ou apenas objetos necessários dentro de uma unidade de tradução. Um exemplo típico pode ser uma função help imprimir os parâmetros aceitos, e que só é chamado a partir da função main definido no mesmo arquivo .c.

6.2.2 / 2 em um projeto de C99:

Se a declaração de um escopo fi le identi fi er para um objecto ou uma função contém a classe de armazenamento especi fi cador estático, o identi fi cador tem interna ligação.

meios ligação interna que o identificador não é visível fora da actual unidade de tradução (como a função help de acima).

Volátil

Volátil é uma coisa diferente: ( 6.7.3 / 6 )

Um objeto que tem volátil-quali fi cado tipo pode ser modi fi cados de maneiras desconhecidas a implementação ou ter outra efeitos colaterais desconhecidos. portanto, qualquer expressão referindo-se a um objecto, tal serão avaliados rigorosamente de acordo com as regras da máquina abstrata, como descrito em 5.1.2.3. Além disso, em cada seqüência de apontar o último valor armazenado no objeto deve acordar com que prescrito pelo abstract máquina, excepto como Modi fi ed pela incógnitas mencionado anteriormente.

A norma fornece um excelente exemplo para um exemplo onde volatile seria redundante ( 5.1.2.3/8 ):

Uma implementação pode de fi ne um um-para-um entre abstratas e reais semântica: no cada ponto de sequência, os valores de os objetos reais concordaria com aqueles especificados pelo abstrato semântica. O volatile palavra-chave então, seria redundante.

pontos de seqüência são pontos onde o efeito de efeitos colaterais sobre o máquina abstrata estão concluídas (isto é, as condições externas, como os valores das células de memória são não incluídas). Entre a direita ea esquerda do && e ||, após ; e retornar de uma chamada de função são pontos de seqüência, por exemplo.

O semântica abstratas é o que o compilador pode deduzir vendo apenas a seqüência de código dentro de um determinado programa. Efeitos de otimizações são irrelevantes aqui. semântica reais incluem o efeito de efeitos colaterais por escrito para objetos (por exemplo, a alteração de células de memória). Qualificar um objeto como meios voláteis se obtém sempre o valor de um objeto direto da memória ( "conforme alterada pelos fatores desconhecidos"). A Norma não mencionar tópicos em qualquer lugar, e se você deve confiar na ordem de mudanças, ou na atomicidade de operações, você deve usar formas dependentes da plataforma para garantir que.

Para uma fácil de entender visão, a Intel tem um ótimo artigo sobre ele aqui .

O que devo fazer agora?

Mantenha declarando seu arquivo-escopo de dados (global) como volátil. Dados globais em si não significa que o valor das variáveis ??será igual ao valor stored na memória. E estático só fazer seus objetos local para a actual unidade de tradução (os arquivos .c atuais e todos os outros arquivos # include'ed por ele).

Outras dicas

Em primeiro lugar, deixe-me mencionar que uma variável global estática, é o mesmo que uma variável global, exceto que você está limitando a variável para o escopo do arquivo. Ou seja, você não pode usar essa variável global em outros arquivos via a palavra-chave extern.

Assim você pode reduzir a sua pergunta para variáveis ??globais vs variáveis ??voláteis.

Agora, para volátil:

Como const, volatile é um modificador de tipo.

A palavra-chave volatile foi criado para evitar otimizações do compilador que podem tornar o código incorreto, especificamente quando há eventos assíncronos.

Objetos declarados como volatile não podem ser utilizados em determinadas otimizações.

O sistema sempre lê o verdadeiro valor atual de um objeto volátil no ponto em que é usado, mesmo se uma instrução anterior pediu um valor a partir do mesmo objeto. Além disso, o valor do objeto é escrito imediatamente em missão. Isso significa que não há cache de uma variável volátil para um registro de CPU.

Dr. Jobb de tem um ótimo artigo sobre volátil.

Aqui está um exemplo de artigo do Dr. Jobb:

class Gadget
{
public:
    void Wait()
    {
        while (!flag_)
        {
            Sleep(1000); // sleeps for 1000 milliseconds
        }
    }
    void Wakeup()
    {
        flag_ = true;
    }
    ...
private:
    bool flag_;
};

Se o compilador vê que Sleep() é uma chamada externa, ele assumirá que Sleep() não pode alterar o valor da variável do Flag_. Assim, o compilador pode armazenar o valor de flag_ num registo. E, nesse caso, isso nunca vai mudar. Mas se outro segmento chamadas de despertar, o primeiro segmento ainda está lendo no registo do CPU. Wait() nunca vai acordar-up.

Então, por que não apenas nunca variáveis ??de cache em registros e evitar completamente o problema? Acontece que essa otimização pode realmente lhe poupar uma grande quantidade de tempo total. Então C / C ++ permite que você explicitamente desativá-lo através da palavra-chave volatile.

O fato acima, que flag_ foi uma variável de membro, e não uma variável global (nem estática global) não importa. A explicação, segundo o exemplo dá o raciocínio correto, mesmo se você está lidando com variáveis ??globais (e variáveis ??globais estáticos).

Um equívoco comum é que declarar uma volatile variável é suficiente para garantir a segurança do thread. Operações na variável ainda não são atômica, mesmo que eles não são "em cache" nos registos

volátil com ponteiros:

volátil com ponteiros, funciona como const com ponteiros.

Uma variável de meios tipo volatile int * que a variável que o ponteiro aponta é volátil.

Uma variável de meios tipo int * volatile que o ponteiro em si é volátil.

A palavra-chave "volátil", sugere o compilador não fazer certas otimizações no código envolvendo essa variável; se você usar apenas uma variável global, nada impede que o compilador erroneamente otimizar seu código.

Exemplo:

#define MYPORT 0xDEADB33F

volatile char *portptr = (char*)MYPORT;
*portptr = 'A';
*portptr = 'B';

Sem "volátil", a primeira gravação pode ser otimizado para fora.

A palavra-chave volátil diz ao compilador para se certificar de que variável nunca será armazenada em cache. Todos os acessos a ela deve ser feita de forma consistente a ter um valor consistente entre os tópicos. Se o valor da variável deve ser alterado por outro segmento enquanto você tem um loop de verificação para a mudança, você quer que a variável a ser voláteis como não há nenhuma garantia de que um valor variável regular não serão armazenados em cache em algum ponto e o loop só vai assumir que permanece o mesmo.

variável volátil na Wikipedia

Eles podem não estar em diferente em seu ambiente atual, mas mudanças sutis podem afetar o comportamento.

  • hardware diferente (mais processadores, arquitetura de memória diferente)
  • Uma nova versão do compilador com uma melhor otimização.
  • variação aleatória no tempo entre threads. Um problema só pode ocorrer uma vez em 10 milhões.
  • configurações de otimização do compilador diferente.

É muito mais seguro a longo prazo para usar construções multithreading adequadas desde o início, mesmo se as coisas parecem funcionar por enquanto sem eles.

É claro que, se o seu programa não é multi-threaded, então não importa.

resposta

I +1 de friol. Eu gostaria de acrescentar algumas precisões quanto parece haver um monte de confusões em diferentes respostas:. C do volátil não é de Java volátil

Então, primeiro, compiladores podem fazer um monte de otimizações no com base nos dados de fluxo do seu programa, volátil impede C que, ele garante que você realmente carga / loja para a localização de cada vez (em vez de usar registros de limpá-lo para fora, por exemplo). É útil quando você tem uma memória mapeada porta IO, como fora pontas de friol.

Volátil em C não tem nada a ver com caches de hardware ou multithreading. Não insira cercas de memória, e você tem absolutamente nenhuma garanty da ordem de operações se dois threads fazer acessos a ele. palavra-chave volátil de Java faz exatamente isso, porém:. inserção de cercas de memória quando necessário

meios variáveis ??voláteis que o valor assinged a ele não é constante, ou seja, se uma função que contém uma variável volátil "a = 10" e a função é a adição de 1 em cada chamada dessa função, em seguida, ele sempre retornará valor atualizado. { volatile int a=10; a++; } quando a função acima é chamado de novo e de novo, em seguida, a variável a não ser re-inicializado a 10, sempre irá mostrar o valor atualizado até o programa é executado. 1 saída = 10 em seguida, 11 em seguida, 12 e assim por diante.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top