2014-05-22 14 views
5

Ho due file di codice sorgente C; un file contiene una dichiarazione come la seguente:La parola chiave extern è necessaria quando si fa riferimento a una variabile volatile dichiarata in un altro file sorgente C?

volatile unsigned char flag=0; 

L'altro file C contiene un riferimento come ad esempio:

extern unsigned char flag; 

È questo il corretto e sicuro, o dovrebbe la parola chiave volatile essere ripetuto ogni volta che fa riferimento alla variabile ? Ad esempio

extern volatile unsigned char flag; 
+2

Si sta utilizzando un compilatore C o C++? Non sembra che dovresti usare il tag 'C++' qui. –

+0

Ora, se volevi sapere se la risposta sarebbe diversa tra C e C++, va bene. Utilizza entrambi i tag ** e spiega nella tua domanda in che modo ti interessano entrambe le lingue **. –

+0

Il compilatore, avendo solo quella * dichiarazione * extern e generando il codice per accedere alla variabile ovviamente non può sapere che si suppone che sia trattato come volatile. Il linker non "aggiusta" quel codice, non è il suo lavoro. Non puoi ometterlo. –

risposta

8

No, non è corretto.

Tutte le dichiarazioni di una stessa necessità variabile da utilizzare lo stesso tipo esatto, e volatile fa parte del tipo (extern non è)

Una buona pratica per la verifica extern dichiarazioni è quello di metterli in un file di intestazione è incluso anche nell'unità di compilazione in cui esiste la definizione. Quindi il compilatore controllerà la correttezza.

Notice what happens if you do that on this example.

prog.c:2:22: error: conflicting type qualifiers for ‘flag’ 
extern unsigned char flag; 
        ^
prog.c:1:24: note: previous definition of ‘flag’ was here 
volatile unsigned char flag=0; 
+0

Evito in particolare di mettere qualcosa sul compilatore usando ottimizzazioni che non dovrebbero essere applicate alle variabili volatili nella mia risposta, al fine di evitare l'apparenza che tale trattamento è garantito. Se vuoi * quel * comportamento, fai un puntatore e getta via 'volatile'. Ma l'uso di definizioni incompatibili è un comportamento indefinito e può portare a cose ben peggiori che non rispettano la volatilità. –

4

Alcune citazioni dallo standard C99 (il corsivo è mio)

6.2.5/25 Tipo

Qualsiasi tipo finora detto è un tipo non qualificato. Ogni tipo non qualificato di ha diverse versioni qualificate del suo tipo, corrispondenti alle combinazioni di uno, due o tutti e tre i qualificatori const, volatile e restrittivo. Le versioni qualificato o non qualificato di tipo sono distinti tipi

6.2.7/2 "tipo compatibile e tipo composito"

Due tipi hanno tipo compatibile se i loro tipi sono uguali.

...

Tutte le dichiarazioni che si riferiscono allo stesso oggetto o funzione avrà tipo compatibile; altrimenti, , il comportamento non è definito.

Se pensate al vostro esempio specifico per un momento, come sarebbe il codice che vede solo la seguente dichiarazione:

extern unsigned char flag; 

hanno alcuna idea che flag avrebbe bisogno di essere trattati come volatile?

Inoltre, indipendentemente dalla tua domanda, tieni presente che il numero volatile di solito non è sufficiente per gestire l'accesso tramite più thread (nel caso in cui sia ciò che intendi).

+0

Il termine "One Definition Rule" è usato per il codice C nello stesso modo in cui è in C++? –

+1

@ Ben: Non penso che il documento C standard usi il termine (mentre lo standard C++ lo fa). Ma, penso che il concetto di "una definizione" valga anche per C, anche se non è esplicitamente usato nel documento standard. –