2009-06-11 22 views
12

Ho un problema con un codice di basso livello che sto scrivendo, ho bisogno di usare oggetti come volatili, ma non è necessariamente così che voglio che i tipi siano dichiarati come volatili (per ragioni di riusabilità). Posso tuttavia definire il puntatore a una variante qualificata di una struttura come dettagliato nel seguente segmento.Semantica volatile in C99

struct x { 
    int bar; 
}; 

struct x foobar; 
... 
volatile struct x *foo = &foobar; 

Ora foo è effettivamente un puntatore ad un oggetto del tipo:

volatile struct x { 
    volatile int x; 
}; 

dal volatile, si applicano a tutti i membri struct. Ora la mia domanda è quando un oggetto contiene un puntatore a un altro oggetto, come si applica la volatilità?

struct x { 
    struct y *bar; 
}; 

Sarà un puntatore a un'istanza volatile x quindi poi trattare questo come:

volatile struct x { 
    struct y * volatile bar; 
}; 

o come:

volatile struct x { 
    volatile struct y * volatile bar; 
}; 

Ho letto attraverso lo standard C, ed è non è molto chiaro su questo, e posso facilmente interpretare la formulazione in più modi.

risposta

4

Nell'esempio si ottenere un puntatore volatile, questo è tutto, la volatilità non è estesa all'oggetto.

L'espansione sulla mia risposta volatile è un atomico rilassato, che significa che l'accesso è atomico, ma le istruzioni non lo saranno. Quindi non è possibile incrementare o decrementare in modo flessibile un volatile, quindi non è possibile utilizzare un puntatore volatile per l'interation, solo operazioni store/load (assigment). Lo stesso vale per un int o un altro numero, e anche volatile non funzionerà con i float perché vengono elaborati nella pipeline FPU, non nella CPU. Tutto sommato volatile non è troppo utile, ma i compilatori di Microsoft posizionano automaticamente le guardie di istruzione intorno ai volatili, rendendoli veri valori atomici, ma questo non fa parte dello standard.

+0

http://www.netrino.com/node/80 Sembra supportare questa idea. Non ho mai letto su volitivo. Roba buona. – Kieveli

+1

"volatile non è troppo utile": non si conosce il software per PC, ma nei sistemi embedded, sono essenziali per la dichiarazione di registri hardware o variabili che possono essere modificati negli interrupt. –

+0

Ottimo punto! Sono passati alcuni anni dal mio ultimo progetto incorporato, quindi l'ho dimenticato. Comunque ha funzionato perché era per carichi e negozi. Sul PC è facile dimenticare la maggior parte degli interrupt mentre vengono sottratti dall'AP del sistema operativo. –

2

Leggendo lo standard here, sembra che il puntatore sia volatile, ma non il contenuto effettivo della struttura stessa. L'ho interpretato dall'esempio fornito, const t * volatile p (nella parte inferiore del link). La formulazione, però, è vago, ma credo che questo sarebbe un esempio simile:

struct foo { 
    int bar; 
}; 

struct foo *volatile x; 

Si noti che non ho provato questo, quindi potrebbe essere clamorosamente errata ... è semplicemente quello che ho raccolti da una rapida lettura dello standard.

Inoltre, cdecl chiarisce parte della vaghezza.Per esempio:

cdecl> spiegare volatile struct x* foo
dichiarare foo come puntatore a struct volatili x

considerando quanto segue:

cdecl> spiegare struct x* volatile foo
dichiarare foo come volatile puntatore a struct x

In un'istanza, la struttura è volatile. Nell'altro, il puntatore.

+1

quindi non potresti semplicemente fare struct volatile x * volatile foo; per un puntatore e una struttura volatile? – Earlz

+0

@ pearl: Sì. Esattamente. struct volatile x * volatile foo è un puntatore volatile a una struttura volatile x. – FreeMemory