Restrict
La parola chiave restrict
è usata nel linguaggio C (a partire dallo standard C99) per qualificare un puntatore come non soggetto ad aliasing da parte di altri puntatori non dichiarati a partire da esso. Nel dichiarare un puntatore restrict
, il programmatore esegue una dichiarazione di intento, informando il compilatore che, nel suo intero ciclo di vita, solo quel puntatore ed eventualmente altri puntatori derivati a partire da esso saranno usati per accedere all'oggetto puntato. Se la dichiarazione di intento è violata dal programmatore e un altro puntatore è usato per accedere all'oggetto, il comportamento del programma è indefinito.
Tale informazione consente al compilatore di generare codice meglio ottimizzato: in principio, l'aggiunta di restrict
allo standard C consente di colmare il divario rispetto a Fortran in applicazioni di calcolo numerico.[1]
Lo standard del linguaggio C++ non prevede la parola chiave restrict
, ma molti compilatori implementano una parola chiave non-standard che fornisce un effetto analogo alla controparte in C, ad esempio __restrict__
in GCC[2] o __restrict
e __declspec(restrict)
in Visual C++.[3]
Ottimizzazione
Se il compilatore è certo che solo un puntatore può accedere ad un blocco di memoria, è possibile generare codice meglio ottimizzato, ad esempio modificando l'ordine delle istruzioni per eseguire tutte le operazioni di load
o store
consecutivamente, oppure evitando di caricare più volte uno stesso valore (sapendo che non può essere modificato tramite un altro puntatore restrict
). Ad esempio, data la funzione
void updatePtrs(size_t *ptrA, size_t *ptrB, size_t *val) { *ptrA += *val; *ptrB += *val; }
i puntatori ptrA
, ptrB
, e val
potrebbero accedere ad una stessa regione di memoria (pointer aliasing), per cui il compilatore deve tenere conto di questa possibilità nel generare il codice macchina. Ad esempio, gcc -O3 -S
(usando gcc versione 8.2) genera il seguente assembly x86-64 per il corpo della funzione
movq (%rdx), %rax addq %rax, (%rdi) movq (%rdx), %rax addq %rax, (%rsi) ret
Se l'aliasing è escluso, qualificando i puntatori come restrict
nella dichiarazione
void updatePtrs(size_t * restrict ptrA, size_t * restrict ptrB, size_t * restrict val);
il compilatore può legittimamente assumere che ptrA
, ptrB
, e val
accederanno sempre a regioni di memoria non sovrapposte e operazioni eseguite tramite un puntatore non avranno effetto sugli oggetti riferiti da altri puntatori (è comunque responsabilità del programmatore di garantire questo fatto nella scrittura del codice). Questo rende superfluo leggere nuovamente il valore puntato da val
dopo aver eseguito la prima istruzione, e l'assembly diventa
movq (%rdx), %rax addq %rax, (%rdi) addq %rax, (%rsi) ret
Note
- ^ Ulrich Drepper, Memory part 5: What programmers can do, in What every programmer should know about memory, lwn.net, 23 ottobre 2007.«"...The default aliasing rules of the C and C++ languages do not help the compiler making these decisions (unless restrict is used, all pointer accesses are potential sources of aliasing). This is why Fortran is still a preferred language for numeric programming: it makes writing fast code easier. (In theory the restrict keyword introduced into the C language in the 1999 revision should solve the problem. Compilers have not caught up yet, though. The reason is mainly that too much incorrect code exists which would mislead the compiler and cause it to generate incorrect object code.)"»
- ^ Using the GNU Compiler Collection: Restricted Pointers, su gcc.gnu.org.
- ^ __restrict, su msdn.microsoft.com.
Bibliografia
- ISO/IEC 9899:TC2 Committee Draft (PDF), ISO, 6 maggio 2005, pp. 108–112. URL consultato il 22 dicembre 2008.
Collegamenti esterni
- Demystifying The Restrict Keyword: explanation and examples of use
- Douglas Walls, How to Use the restrict Qualifier in C, su oracle.com, Oracle™. URL consultato il 21 novembre 2012.
- Restricted Pointers in C: the original rationale behind the definition
![](http://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Computer_n_screen.svg/24px-Computer_n_screen.svg.png)