Si consideri il seguente codice:`const T * restrict` garantisce che l'oggetto puntato non venga modificato?
void doesnt_modify(const int *);
int foo(int *n) {
*n = 42;
doesnt_modify(n);
return *n;
}
in cui la definizione di doesnt_modify
non è visibile per il compilatore. Pertanto, è necessario supporre che doesnt_modify
modifichi l'oggetto n
punti e debba leggere *n
prima dello return
(l'ultima riga non può essere sostituita da return 42;
).
Assumendo, doesnt_modify
non modifica *n
. Ho pensato a quanto segue per consentire l'ottimizzazione:
int foo_r(int *n) {
*n = 42;
{ /* New scope is important, I think. */
const int *restrict n_restr = n;
doesnt_modify(n_restr);
return *n_restr;
}
}
Questo ha lo svantaggio che il chiamante di doesnt_modify
deve dire al compilatore *n
non viene modificato, piuttosto che la funzione stessa potrebbe dire al compilatore tramite il suo prototipo . Semplicemente restrict
-qualificare il parametro su doesnt_modify
nella dichiarazione non è sufficiente, cfr. “Is top-level volatile
or restrict
significant [...]?”.
Durante la compilazione con gcc -std=c99 -O3 -S
(o Clang con le stesse opzioni), tutte le funzioni sono compilate per l'assemblaggio equivalente, tutte rilette lo da *n
.
Sarebbe un compilatore essere consentito di fare questa ottimizzazione (sostituire l'ultima riga da
return 42;
) perfoo_r
? In caso contrario, c'è un modo (portatile, se possibile) per dire al compilatoredoesnt_modify
non modifica a cosa punta il suo argomento? C'è un modo in cui i compilatori capiscono e fanno uso di?C'è qualche funzione in UB (purché
doesnt_modify
non modifichi il punto d'impatto del suo argomento)?
Perché penso, restrict
potrebbe aiuto qui (da C11 (n1570) 6.7.3.1 “Definizione formale di restrict
”, p4 [emph mio.]):
[In questo caso, è B
il blocco interno di foo_r
, P
è n_restr
, T
è const int
, e X
è l'oggetto denotato da *n
, credo.]
Durante ogni exec ution di
B
, lasciareL
un qualsiasi valore che ha&L
basato suP
. SeL
è utilizzato per accedere al valore dell'oggettoX
che designa, eX
è anche modificato (con qualsiasi mezzo), quindi i seguenti requisiti si applicano:T
non sarà const qualificati. [...]
$ clang --version
Ubuntu clang version 3.5.0-4ubuntu2 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
versione di gcc 4.9.2 è, su un target x86 a 32 bit.
È legale per 'doesnt_modify2' per escludere la costanza e modificare l'oggetto puntato, a condizione che l'oggetto stesso non sia dichiarato' const'. –
@ T.C. Sì, questo è il punto. La domanda è, se 'restrict' fa la differenza qui. – mafso
Interessante: prometti che nient'altro lo alias e che questo puntatore non può modificarlo. Sono molto curioso di vedere cosa significa. – templatetypedef