begränsa
I programmeringsspråket C är restrict
ett nyckelord , introducerat av C99-standarden , som kan användas i pekardeklarationer . Genom att lägga till denna typ qualifier , tipsar en programmerare till kompilatorn att under pekarens livstid kommer ingen annan pekare att användas för att komma åt objektet som den pekar på. Detta gör att kompilatorn kan göra optimeringar (till exempel vektorisering) som annars inte skulle ha varit möjliga.
begränsa
begränsar effekterna av pekaraliasing , vilket hjälper till med optimeringar . Om avsiktsförklaringen inte följs och objektet nås av en oberoende pekare kommer detta att resultera i odefinierat beteende .
Optimering
Om kompilatorn vet att det bara finns en pekare till ett minnesblock kan den producera bättre optimerad kod. Till exempel:
void updatePtrs ( size_t * ptrA , size_t * ptrB , size_t * val ) { * ptrA += * val ; * ptrB += * val ; }
kan pekarna ptrA
, ptrB
och val
referera till samma minnesplats , så kompilatorn kan generera mindre optimal kod:
; Hypotetisk RISC-maskin. ldr r12 , [ val ] ; Ladda minne vid val till r12. ldr r3 , [ ptrA ] ; Ladda minne vid ptrA till r3. lägg till r3 , r3 , r12 ; Utför addition: r3 = r3 + r12. str r3 , [ ptrA ] ; Lagra r3 på minnesplatsen ptrA, uppdatera värdet. ldr r3 , [ ptrB ] ; 'load' kan behöva vänta tills föregående 'store' är klar. ldr r12 , [ val ] ; Måste ladda en andra gång för att säkerställa konsistens. lägg till r3 , r3 , r12 str r3 , [ ptrB ]
Men om nyckelordet restrict
används och ovanstående funktion deklareras som
void updatePtrs ( size_t * limit ptrA , size_t * limit ptrB , size_t * limit val );
då tillåts kompilatorn att anta att ptrA
, ptrB
och val
pekar på olika platser och att uppdatera minnesplatsen som refereras av en pekare kommer inte att påverka minnesplatserna som refereras av de andra pekarna. Programmeraren, inte kompilatorn, är ansvarig för att se till att pekarna inte pekar på identiska platser. Kompilatorn kan t.ex. ordna om koden, först ladda alla minnesplatser, sedan utföra operationerna innan resultaten skickas tillbaka till minnet.
ldr r12 , [ val ] ; Observera att val nu bara laddas en gång. ldr r3 , [ ptrA ] ; Dessutom, alla 'belastningar' i början ... ldr r4 , [ ptrB ] lägg till r3 , r3 , r12 lägg till r4 , r4 , r12 str r3 , [ ptrA ] ; ... alla 'butiker' till slut. str r4 , [ ptrB ]
Ovanstående monteringskod är kortare eftersom val
endast laddas en gång. Dessutom, eftersom kompilatorn kan ordna om koden mer fritt, kan kompilatorn generera kod som körs snabbare. I den andra versionen av exemplet ovan sker alla lagringsoperationer efter laddningsoperationerna ,
vilket
säkerställer att processorn inte behöver blockera mitt i koden för att vänta tills lagringsoperationerna är
klara.
Observera att den verkligt genererade koden kan ha olika beteenden. Fördelen med ovanstående mini-exempel tenderar att vara liten, och i verkliga fall tenderar stora slingor som gör tung minnesåtkomst att vara det som verkligen underlättas av begränsa.
Som nämnts ovan, hur felaktig kod beter sig är odefinierat , kompilatorn säkerställer bara att den genererade koden fungerar korrekt om koden följer avsiktsförklaringen.
Stöd av C++-kompilatorer
C++ har inte standardstöd för restrict
, men många kompilatorer har motsvarigheter som vanligtvis fungerar i både C++ och C, såsom GCC :s och Clang :s __restrict__
och Visual C++ :s __declspec(restrict)
. Dessutom stöds __restrict av dessa tre kompilatorer.
Den exakta tolkningen av dessa alternativa sökord varierar beroende på kompilatorn:
- I kompilatorer i Unix-stil som GCC och Clang betyder
__restrict
och__restrict__
exakt detsamma som deras C-motsvarighet. Tillägg inkluderar att tillåta dem att tillämpas på referenstyper ochdetta
. - I Visual C++ finns flera no-alias-kvalificerare:
-
__declspec(restrict)
gäller funktionsdeklarationen och antyder att den returnerade pekaren inte är alias. -
__restrict
används på samma ställe somrestrict
, men no-alias-tipset sprids inte som irestrict
. Det är även utökat för fackföreningstyper .
-
Kompilatorvarningar
För att förhindra felaktig kod försöker vissa kompilatorer och andra verktyg upptäcka när överlappande argument har skickats till funktioner med parametrar markerade limit
. CERT C-kodningsstandarden anser att missbruk av restriktioner
och biblioteksfunktioner som är markerade med den (EXP43-C) är en trolig källa till programvarubuggar, även om det i november 2019 inte är känt att några sårbarheter har orsakats av detta.
- "ISO/IEC 9899:TC2-kommittéutkast" (PDF) . ISO . 6 maj 2005. s. 108–112 . Hämtad 2008-12-22 .
externa länkar
- Demystifying The Restrict Keyword : förklaring och exempel på användning
- Walls, Douglas. "Hur man använder begränsningskvalificeringen i C" . Oracle™ . Hämtad 2012-11-21 .
- Begränsade pekare i C : den ursprungliga motiveringen bakom definitionen