In der Programmiersprache C ist der C99-Standard restrictein Schlüsselwort, das in Zeigerdeklarationen verwendet werden kann . Das Schlüsselwort restrict ist eine Absichtserklärung, die der Programmierer dem Compiler gibt . Es gibt an, dass für die Lebensdauer des Zeigers nur der Zeiger selbst oder ein direkt abgeleiteter Wert (z. B. pointer + 1) verwendet wird, um auf das Objekt zuzugreifen, auf das er zeigt. Dies begrenzt die Auswirkungen des Zeiger-Aliasing und hilft bei Optimierungen. Wenn die Intent-Anweisung verletzt wird und das Objekt von einem unabhängigen Zeiger erreicht wird, führt dies zu undefiniertem Verhalten. Die Verwendung des Schlüsselworts restrict ermöglicht im Prinzip die gleiche Leistung wie das gleiche in Fortran geschriebene Programm .
C ++ bietet keine Standardunterstützung für restrict, aber viele Compiler verfügen über Entsprechungen, die normalerweise in C ++ und C funktionieren, z. B. __restrict__ für GCC und Clang und __restrict und __declspec (einschränken) für Visual C ++ .
Wenn der Compiler weiß, dass es nur einen Zeiger auf einen Speicherblock gibt, kann er besser optimierten Code erzeugen.
Beispielsweise :
void updatePtrs(size_t *ptrA, size_t *ptrB, size_t *val) { *ptrA += *val; *ptrB += *val; }In dem obigen Code, Zeiger ptrA, ptrBund val können auf die gleiche Speicherstelle beziehen, so dass der Compiler einen weniger optimalen Code erzeugen kann:
load R1 ← *val ; Charge la valeur pointé par val load R2 ← *ptrA ; Charge la valeur pointé par ptrA add R2 += R1 ; Effectuer une Addition set R2 → *ptrA ; mettre à jour la valeur pointé par ptrA ; De même pour ptrB, notez que val est chargé à deux reprises, parce que ; ptrA peut être égal à val (c'est à dire, pointe vers le même emplacement). load R1 ← *val load R2 ← *ptrB add R2 += R1 set R2 → *ptrBWenn jedoch das Schlüsselwort restrict verwendet wird und die obige Funktion wie folgt deklariert ist:
void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val);dann wird der Compiler erlaubt zu annehmen , dass ptrA, ptrBund valzeigen Sie auf verschiedenen Standorten und daß das Aktualisieren eines Zeigers wirkt sich nicht auf andere Zeiger. Der Programmierer (nicht der Compiler) ist dafür verantwortlich, dass Zeiger nicht auf dieselben Stellen verweisen.
Jetzt kann der Compiler wie folgt besseren Code generieren:
load R1 ← *val load R2 ← *ptrA add R2 += R1 set R2 → *ptrA ; Notez que val n'est pas rechargé, ; parce que le compilateur sait que c'est inchangé load R2 ← *ptrB add R2 += R1 set R2 → *ptrBBeachten Sie, dass der Assemblycode kürzer ist, da der Wert, auf den von valzeigt, nur einmal geladen wird.