2016-06-22 38 views
9

dire che ho uno structpuntatori in una struct volatile C

typedef struct A{ 

int a1; 
int *a2; 

}A_t; 

Ora, se io dichiaro un esempio di questo struct ad essere volatili -

volatile A_t trial; 

e io uso un puntatore volatile per l'accesso questa struttura volatile.

volatile A_t *ptrToTrial = &trial; 

Se provo a fare questo:

int *ptrToField = ptrToTrial->a2; 

Dovrebbe ptrToField essere volatili come bene? Il compilatore dovrebbe sapere che prtToField è volatile senza menzione esplicita perché è accessibile tramite ptrToTrial che è volatile?

anche se v'è una funzione -

function trialFunction(A_t *trialptr) 
{ 
    int *p = trialptr->a2; 

} 

Se chiamiamo questa funzione con PTR volatili sopra riportate -

trailFunction(ptrToTrial) 

ottengo un errore: volatile A_t* is incompatible with parameter of type A_t.

Quindi, se cambio la definizione della funzione per includere volatile, non vedo un errore.

function trialFunction(volatile A_t *trialptr) 
{ 
    int *p = trialptr->a2; 

} 

Non dovrebbe il compilatore lamentano anche il puntatore p - perché p è non volatile e trialptr->a2 è volatile?

+1

Il tuo codice non chiarisce come stai usando 'volatile'. Ma sappi che non fa quello che molti pensano che faccia. Infatti, [è praticamente inutile in realtà] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2016.html). –

+2

Solo le cose dichiarate esplicitamente come 'volatile' nello specificatore di tipo saranno volatili. Nel caso precedente, 'trial' e' * ptrToTrial' sono volatili. 'ptrTrial-> a2' è volatile in quanto membro di una struttura volatile. Tuttavia 'ptrToTrial-> a2 [0]' e 'ptrToField [0]' (supponendo che siano validi) non sono volatili. –

+0

"E io uso un puntatore volatile per accedere a questa struttura volatile." 'volatile A_t * ptrToTrial = &trial;' -> No, 'ptrToTrial' non è' volatile', quello a cui punta è 'volatile'. – chux

risposta

1

Si prega di notare che int *a2; nel vostro struct A non è volatile. Così

int *ptrToField = ptrToTrial->a2; 

ptrToField non è volatile.

trailFunction(ptrToTrial) ottiene errore perché la funzione trailFunction aspetta A_t *trialptr, ma si passa volatile A_t*, è ovviamente errore di compilazione.

E infine:

function trialFunction(volatile A_t *trialptr) 
{ 
    int *p = trialptr->a2; 
} 

E 'OK per compilare, perché il tipo a2 s' è int*.

-1

Il mio posizionamento preferito è in genere nella dichiarazione del puntatore. In questo modo, tutti i registri nella struttura saranno trattati dal compilatore come volatili e tuttavia è possibile avere altre istanze (ad esempio basate su RAM) di detta struttura che non sono volatili perché non sono in realtà registri hardware sotto.

vi consiglio quindi di utilizzare:

typedef volatile struct 

have a nice day

+0

"_Have a nice day_"? Sei seduto in un caffè? –

+0

Sì;) http://images.fineartamerica.com/images-medium-large-5/have-a-nice-day-cafe-brian-wallace.jpg – AkrogAmes

3

Should ptrToField be volatile as well?

Con la tua definizione di struct A, la cosa puntato da membro a2 non è dichiarato di essere volatile. Il fatto che una determinata istanza di sia volatile implica che il suo membro è volatile, ma non che la cosa a cui punta è volatile. Questa è la differenza tra int * volatile (equivalente al caso reale) e volatile int *.

L'inizializzazione si descrive ...

int *ptrToField = ptrToTrial->a2; 

... inizializza ptrToField con il valore del puntatore ptrToTrial->a2. Poiché punta a un oggetto volatile, il programma deve caricare il puntatore (un membro di tale oggetto volatile) dalla memoria principale. Poiché la cosa indicata non è (dichiarata) volatile, tuttavia, nessuna informazione viene persa e nessun (nuovo) rischio è inerente alla dichiarazione del tipo di obiettivo ptrToField come semplice int. Certamente non vi è alcun vantaggio nel dichiarare lo stesso ptrToField come volatile.

Inoltre, nel caso non sia chiaro, il nome della variabile ptrToField non è coerente con l'utilizzo a cui viene inserito. Non si inizializza per indicare un membro del proprio struct; piuttosto, lo si inizializza come copia di un membro del proprio struct.

Would the compiler know that prtToField is volatile without explicit mention because it is accessed through ptrToTrial which is volatile?

Non è necessario per esercitare tale conoscenza che potrebbe avere, e che la conoscenza in ogni caso sarebbero suscettibili di essere molto portata limitata. Sa come è stata inizializzata quella variabile, ma potrebbe essere difficile prevedere quando e come il suo valore potrebbe successivamente essere modificato. In ogni caso, qualsiasi informazione non riportata dal tipo dichiarato della variabile non è rilevante per la semantica C standard del tuo programma.

Shouldn't the compiler also complain about the pointer p - because p is non-volatile and trialptr->a2 is volatile?

No, perché anche se trialptr->a2 è volatile, non v'è alcun problema con leggendo il valore (ad un dato punto nel tempo) e assegnando tale valore ad un'altra variabile. I valori degli oggetti sono schemi di bit, non sono né volatili né non-volatili - questa è una caratteristica della loro memorizzazione, come comunicata tramite i lvalue con cui sono accessibili.

+0

Ha senso. Grazie. – Curious91

+0

Quindi non avrebbe sempre senso definire un puntatore volatile in questo modo: A_t volatile * ptrToTrial = &trial; invece di volatile A_t * ptrToTrial = & trial? – Curious91

+1

@ Curious91, 'volatile int *' e 'int volatile *' sono scritti in modo diverso, ma sono equivalenti, proprio come 'volatile int' e' int volatile' sono equivalenti. Questo è lo stesso del tipo qualificatore 'const', che è un contesto più comune per problemi come questo. –