beschränken

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 ++ .

Optimierung

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 *ptrB

Wenn 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 *ptrB

Beachten Sie, dass der Assemblycode kürzer ist, da der Wert, auf den von valzeigt, nur einmal geladen wird.

Verweise

  1. Ulrich Drepper , „  Speicher Teil 5: Was Programmierer können  “ , Was jeder Programmierer über Speicher wissen sollte , sur Was jeder Programmierer über Speicher wissen sollte , lwn.net ,23. Oktober 2007 : "" ... Die Standard-Aliasing-Regeln der Sprachen C und C ++ helfen dem Compiler nicht, diese Entscheidungen zu treffen (sofern keine Einschränkung verwendet wird, sind alle Zeigerzugriffe potenzielle Quellen für Aliasing). Aus diesem Grund ist Fortran immer noch vorhanden Eine bevorzugte Sprache für die numerische Programmierung: Sie erleichtert das Schreiben von schnellem Code. (Theoretisch sollte das in der C-Sprache von 1999 in die C-Sprache eingeführte Restriktionsschlüsselwort das Problem lösen. Compiler haben jedoch noch nicht aufgeholt. Der Grund ist hauptsächlich, dass zu viel Es ist ein falscher Code vorhanden, der den Compiler irreführen und dazu führen würde, dass er falschen Objektcode generiert.) ""

Siehe auch

Zum Thema passende Artikel

Externe Links