Quando si utilizza un puntatore limitare in C, è OK per cambiare una variabile utilizzando il suo identificativo iniziale?
-
30-09-2019 - |
Domanda
Quando si utilizza un puntatore restrict
in C, è OK per modificare la variabile utilizzando la sua iniziale Identifier ? Ad esempio:
int foo = 0;
int * restrict fooPtr = &foo;
++(*fooPtr); // Part 1: foo is 1 (OK)
++foo; // Part 2: foo is 2 (Is this OK?)
int * fooPtr2 = &foo;
++(*fooPtr2); // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer)
... ho cambiato il valore di pippo a foo dopo il restrict
fooPtr è stato creato.
Parte 1 sembra OK per me. Sono confuso su Parte 2 . E da quello che ho capito su restrict
, Parte 3 è male (compilatore lo permette, ma il suo comportamento non è definito, ed è fino al programmatore di non farlo).
Soluzione
No, parte 2 non è OK.
La parte specifica dello standard è 6.7.3.1/4. Questa sezione è piuttosto denso, e richiede pochi rilegge, ma P è un puntatore limitare, e X è un oggetto che viene usato per accedere, e che viene modificato. Quindi nel tuo esempio P è fooPtr
e X è foo
. Poi:
Ogni altro valore assegnabile utilizzato per accedere al valore di X deve anche avere il suo indirizzo sulla base di P.
"sulla base di" è definito nel paragrafo precedente, e per riassumere, il foo
lvalue non hanno il suo indirizzo in base al limitare puntatore P. Quindi la regola è rotto quando si accede l'oggetto foo
attraverso il proprio nome.
Parte 3 non è OK per lo stesso motivo, il *fooPtr2
lvalue non è basata sulla P sia, ma è anche usato per l'accesso X.
dico "Non OK" - per essere precisi, la combinazione di 1 + 2 provoca un comportamento indefinito, così come la combinazione di 1 + 3. Finché in realtà non accedere l'oggetto attraverso il puntatore limitare, nessuno della definizione di limitare "calci in". Se si voleva si potrebbe rimuovere Parte 1, mantenere il puntatore limitare inutilizzato, e poi 2 e 3 sarebbe OK.
Altri suggerimenti
Sì, "parte 3" è un comportamento indefinito. Dalla C99 spec (6.7.3, comma 7):
Un oggetto a cui si accede attraverso un limitare-quali puntatore fi cato ha un associazione speciale con tale puntatore. Questa associazione, definita in 6.7.3.1 sotto, richiede che tutti gli accessi tale uso oggetto, direttamente o indirettamente, il valore di tale particolare puntatore.
Direi 2 # è male. Per esempio, il compilatore potrebbe ottimizzare il caricamento del valore a * fooPtr in un registro, e poi scrivere che valore del registro di nuovo fuori a foo più tardi - dopo la vostra ++ foo, in modo che l'++ foo è perduto.
Supponendo che tutte le parti della sua domanda si verificano nello stesso blocco, non è OK per accedere al valore di foo
direttamente (parte 2), né per l'accesso tramite un altro puntatore (parte 3):
- 6.7.3.1 formale definizione di limitare
Ogni altro valore assegnabile utilizzato per accedere al valore di X è anche il suo indirizzo sulla base di P.
La definizione formale di restrict
è abbastanza difficile da seguire (almeno lo è per me), ma la seguente descrizione meno formale anche dalle somme standard, è abbastanza bene (almeno per questo caso):
Un oggetto a cui si accede tramite un puntatore limitare qualificato ha un'associazione speciale con tale puntatore. Questa associazione, definito in 6.7.3.1 seguito, richiede che tutti gli accessi a tale uso oggetto, direttamente o indirettamente, il valore di quel particolare puntatore.