omezit - restrict

V programovacím jazyce C , restrictje 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 + 1bude pro přístup k objektu, na který odkazuje, použit pouze samotný ukazatel nebo hodnota přímo z něj odvozená (například ).

restrictomezuje úč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 __restrictje 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, __restricta __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 a this.
  • V Visual C ++ je poskytováno více kvalifikátorů bez aliasu:
    1. __declspec(restrict)vztahuje se na deklaraci funkce a naznačuje, že vrácený ukazatel není aliasovaný.
    2. __restrictse používá na stejném místě jako restrict, ale nápověda bez aliasu se nerozšíří jako v restrict. 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, ptrBa 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 restrictje 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, ptrBa valpř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 valje 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 storeoperace probíhají po loadoperacích, což zajišťuje, že procesor nebude muset blokovat uprostřed kódu, aby počkal, až budou storeoperace 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í restrictknihovní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

externí odkazy