omezit - restrict
V programovacím jazyce C , restrict
je klíčové slovo , které mohou být použity v ukazatel prohlášení. Přidáním tohoto kvalifikátoru typu programátor naznačuje kompilátoru, že po celou dobu životnosti ukazatele pointer + 1
bude pro přístup k objektu, na který odkazuje, použit pouze samotný ukazatel nebo hodnota přímo z něj odvozená (například ).
restrict
omezuje účinky aliasingu ukazatele a napomáhá optimalizaci . Pokud není dodržena deklarace záměru a k objektu je přistupováno nezávislým ukazatelem, bude to mít za následek nedefinované chování . Použití tohoto kvalifikátoru typu umožňuje C kódu dosáhnout stejného výkonu jako stejný program napsaný ve Fortranu . Byl představen ve standardu C99 .
C ++ nemá standardní podporu restrict
, ale mnoho překladače mají ekvivalenty, které obvykle pracují v obou C ++ a C, jako je například GCC ‚s a Clang ‘ s __restrict__
, a Visual C ++ ‚s __declspec(restrict)
. Kromě toho __restrict
je podporován těmito třemi překladači. Přesná interpretace těchto alternativních klíčových slov se liší podle překladače:
- V Unix stylu překladačů, jako GCC a Clang,
__restrict
a__restrict__
střední přesně stejné jako jejich C protějšek. Rozšíření zahrnují umožnění jejich použití na referenční typy athis
. - V Visual C ++ je poskytováno více kvalifikátorů bez aliasu:
-
__declspec(restrict)
vztahuje se na deklaraci funkce a naznačuje, že vrácený ukazatel není aliasovaný. -
__restrict
se používá na stejném místě jakorestrict
, ale nápověda bez aliasu se nerozšíří jako vrestrict
. Je také rozšířen pro typy spojení .
-
Optimalizace
Pokud kompilátor ví, že na paměťový blok existuje pouze jeden ukazatel, může vytvořit lépe optimalizovaný kód. Například:
void updatePtrs(size_t *ptrA, size_t *ptrB, size_t *val)
{
*ptrA += *val;
*ptrB += *val;
}
Ve výše uvedeném kódu ukazatele ptrA
, ptrB
a val
mohou odkazovat na stejné místo v paměti , takže kompilátor může generovat méně optimální kód:
; Hypothetical RISC Machine.
ldr r12, [val] ; Load memory at val to r12.
ldr r3, [ptrA] ; Load memory at ptrA to r3.
add r3, r3, r12 ; Perform addition: r3 = r3 + r12.
str r3, [ptrA] ; Store r3 to memory location ptrA, updating the value.
ldr r3, [ptrB] ; 'load' may have to wait until preceding 'store' completes.
ldr r12, [val] ; Have to load a second time to ensure consistency.
add r3, r3, r12
str r3, [ptrB]
Pokud restrict
je však použito klíčové slovo a výše uvedená funkce je deklarována jako
void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val);
pak může kompilátor předpokládat, že ptrA
, ptrB
a val
přejděte na různá umístění a aktualizace umístění paměti odkazovaného jedním ukazatelem nebude mít vliv na umístění paměti odkazovaná jinými ukazateli. Programátor, nikoli překladač, je zodpovědný za zajištění toho, aby ukazatele nesměrovaly na identická umístění. Kompilátor může např. Změnit uspořádání kódu, nejprve načíst všechna paměťová místa a poté provést operace před potvrzením výsledků zpět do paměti.
ldr r12, [val] ; Note that val is now only loaded once.
ldr r3, [ptrA] ; Also, all 'load's in the beginning ...
ldr r4, [ptrB]
add r3, r3, r12
add r4, r4, r12
str r3, [ptrA] ; ... all 'store's in the end.
str r4, [ptrB]
Výše uvedený kód sestavy je kratší, protože val
je načten pouze jednou. Vzhledem k tomu, že kompilátor může uspořádat kód volněji, může kompilátor generovat kód, který se spouští rychleji. Ve druhé verzi výše uvedeného příkladu všechny store
operace probíhají po load
operacích, což zajišťuje, že procesor nebude muset blokovat uprostřed kódu, aby počkal, až budou store
operace dokončeny.
Skutečný generovaný kód může mít odlišné chování. Výhoda s výše uvedeným mini-příkladem má tendenci být malá a v reálných případech mají velké smyčky, které provádějí těžký přístup k paměti, tendenci být tím, čemu skutečně pomáhá omezení.
Jak bylo uvedeno výše, jak se chová nesprávný kód, není definováno , kompilátor zajišťuje pouze to, aby vygenerovaný kód fungoval správně, pokud kód následuje prohlášení o záměru.
Upozornění kompilátoru
Abychom zabránili nesprávnému kódu, pokusí se některé kompilátory a další nástroje zjistit, kdy byly funkcím s vyznačenými parametry předány překrývající se argumenty restrict
. Standard CERT C Coding Standard považuje zneužití restrict
knihovních funkcí s ním označených (EXP43-C) za pravděpodobný zdroj softwarových chyb, i když od listopadu 2019 není známo, že by tím byly způsobeny žádné chyby zabezpečení.
Reference
-
„ISO / IEC 9899: Návrh výboru TC2“ (PDF) . ISO . 6. května 2005: 108–112 . Citováno 2008-12-22 . Citovat deník vyžaduje
|journal=
( pomoc )
externí odkazy
- Demystifikování omezujícího klíčového slova : vysvětlení a příklady použití
- Zdi, Douglasi. Msgstr "Jak používat omezovač v C" . Oracle ™ . Citováno 2012-11-21 .
- Omezené ukazatele v jazyce C : původní zdůvodnění definice