2016-09-07 16 views
6

Ponieważ ścisłe aliasingowanie może pomóc w lepszej optymalizacji kompilatora, C99 wprowadziło słowo kluczowe restrict, które może być użyte jako kwalifikator zmiennej, jeśli programiści gwarantują, że nie będzie on dostępny przez wskaźnik do innego typu. Jednak typowanie między różnymi typami jest nieuniknione z kilku powodów, a to spowoduje, że kompilator przyjmie, że jeden wskaźnik nie jest aliasem drugiego. Dlatego metoda obejścia problemu polega na wyłączeniu globalnej ścisłej optymalizacji aliasingowej poprzez przekazanie -fno-strict-aliasing (flagi GCC). To nie ma sensu, ponieważ mogą istnieć tylko dwa wskaźniki, które nie powinny być w pełni zoptymalizowane. Dlatego warto wprowadzić przeciwne słowo kluczowe o numerze restrict, które mówi kompilatorowi, że nie zakłada, że ​​te dwa wskaźniki wskazują na różne adresy. Jest to trochę podobne do tego, co robi volatile, a to mówi kompilatorowi, że zmienna ta jest bardzo zmieniona, więc traktuj je w specjalny sposób. Czy jest możliwe utworzenie takiego słowa kluczowego?Przeciwne słowo kluczowe "restrict" w C?

EDYCJA: Istnieje sposób na rozwiązanie tego problemu. Zobacz poniżej komentarz do: yano's.

+3

ścisłe aliasing nie gwarantuje, że coś nie będzie dostępne przez więcej niż jeden wskaźnik - tylko, że nie będzie on dostępny (ogólnie) przez wskaźnik do innego typu. 'restrict' jest inne. – Dmitri

+1

Czy masz konkretny MVCE? –

+0

Wdrażam listę połączonych XOR, która będzie typować dwa różne typy wskaźników. To sprawia, że ​​GCC jest zdezorientowany i tworzy wyjątki wykluczające bez ustawienia flagi '-fno-strict-aliasing'. Myślę, że wyłączenie globalnej optymalizacji to taka szkoda. –

Odpowiedz

0

względu na kod:

int foo(int * restrict p) 
{ 
    *p = 3; 
    someOutsideFunction(); 
    return *p; 
} 

kompilator ma prawo zakładać, że tak długo, jak p jest w zakresie, żaden obiekt która jest napisane przy użyciu *p być dostępne będą za pośrednictwem innych niż poprzez wskaźnik środków, które jest kopiowane lub w inny sposób "wyprowadzane" zp. Inne wskaźniki do obiektu mogą istnieć w dowolnym miejscu we wszechświecie, ale do momentu zwrócenia foo żaden z nich nie będzie dostępny, aby uzyskać dostęp do *p. W konsekwencji, kompilator może zastąpić powyższe z

int foo(int * restrict p) 
{ 
    someOutsideFunction(); 
    *p = 3; 
    return 3; 
} 

ponieważ może zobaczyć, że żaden wskaźnik kopiowane lub pochodzi z p kiedykolwiek wystawiony w taki sposób, że someOutsideFunction mógł ją zobaczyć, a tym samym nie uzasadniony sposób someOutsideFunction aby uzyskać dostęp do obiekt *p.

Jeśli someOutsideFunction może - bez wiedzy na przetwarzanie kompilatora foo --include słowo kluczowe zachowywał jako przeciwieństwo restrict, i może pozwolić na to, aby uzyskać dostęp do obiektu określonego przez p [przyjmującej wskaźnik do tego obiektu z zmiennej globalnej lub inne takie środki], które uniemożliwiałyby kompilatorowi przetwarzanie foo wiedzieć, czy someOutsideFunction może uzyskać dostęp do *p, a tym samym niemożliwe, aby wiedział on, czy może bezpiecznie zastosować wskazaną optymalizację.