2010-05-05 18 views
18

O ile rozumiem, GCC obsługuje wszystkie funkcje C99 w C++. Ale w jaki sposób ścisłe aliasingowanie C99 jest obsługiwane w kodzie C++?C99 ścisłe zasady aliasingu w C++ (GCC)

Wiem, że rzutowanie za pomocą rzutów C między niespokrewnionymi typami nie jest ściśle-aliasingowe i może generować niepoprawny kod, ale co z C++? Ponieważ ścisłe aliasing nie jest częścią standardu C++ (czy to prawda?), GCC musi określać samą semantykę.

Rysunek const_cast i static_cast rzucają między pokrewnymi typami, dlatego są bezpieczne, natomiast reinterpret_cast może łamać zasady ścisłego aliasingu.

Czy to poprawne zrozumienie?

Odpowiedz

31

Nie, prawdopodobnie miksujesz różne rzeczy.

Rygorystyczne reguły dotyczące aliasów nie mają absolutnie nic wspólnego ze standardem C99. Rygorystyczne zasady aliasingu są zakorzenione w częściach standardu, które były obecne w C i C++ od początku [standaryzowanych] razy. Klauzula, która zabrania dostępu do obiektu jednego rodzaju przez lwartości innego typu, występuje w C89/90 (6.3), a także w C++ 98 (3.10/15). Na tym polega ścisłe aliasing, nie więcej, nie mniej. Po prostu nie wszystkie kompilatory chciały (lub ośmieliły się) go wymusić lub na nim polegać. Zarówno języki C, jak i C++ są czasem używane jako języki "wysokiego poziomu", a ścisłe reguły aliasingu często kolidują z takimi zastosowaniami. To właśnie GCC dokonało tego śmiałego posunięcia i postanowiło zacząć polegać na regułach ścisłego aliasingu w optymalizacjach, często pobierając skargi z tych "montażowych" typów.

To prawda, że ​​najprostszym sposobem złamania restrykcyjnych reguł aliasingu w C++ jest reinterpret_cast (i oczywiście obsada w stylu C). Jednakże static_cast mogą być również stosowane do tego celu, gdyż pozwala, aby przerwać ścisłe wygładzanie za pomocą void * jako typ pośredni w „łańcuch” cast

int *pi; 
... 
double *pd = static_cast<double *>(static_cast<void *>(pi)); 

const_cast nie rozkłada ścisłego aliasingu w kompilatorze zasadami.

Co do C99 ... To, co wprowadził C99, to kwalifikator restrict. Jest to bezpośrednio związane z aliasingiem, ale nie jest to tak zwane ścisłe aliasing jako takie.

+1

Masz rację, myślałem C99 'ograniczać' słowo kluczowe, zamiast ścisłego aliasingu. Z jakiegoś powodu utkwiło mi to w głowie ("C99" + "ścisłe aliasing"). –

+0

Więc czym dokładnie jest ta klauzula?Czy oznacza to, że każdy kod C89/C99/C++ 98, który łamie ścisłe reguły aliasingu, jest technicznie niepoprawny (z wyłączeniem specyficznych dla kompilatora przełączników, takich jak -fno-strict-aliasing)? –

+0

@Checkers: Dodałem numery do mojej odpowiedzi. I tak, kod łamiący zasady ścisłego aliasingu wykazuje niezdefiniowane zachowanie, również w C89 i C++ 98. – AnT

4

może również złamać reguły aliasingu, ponieważ kompilator zapewnia, że ​​typ docelowy jest powiązany z rzeczywistym typem środowiska wykonawczego obiektu. Rozważ:

extern void f(double*, int*); // compiler may optimize assuming that arguments don't overlap 
double d; 
void* pv = &d; 
int* pi = static_cast<int*>(pv); 
f(&d, pi); // assumption is violated 
2

Koncepcja jest taka sama w Cpp; w tym celu możesz używać rzutów w stylu C, aby poprowadzić cię przez to, co jest uważane za surowe aliasing.

W skrócie: nie, podejście do używania rzutowania Cpp (które zostało opisane) nie będzie bezpiecznie obejmować wszystkie przypadki. Jednym z typowych sposobów łamania reguł jest użycie static_cast do rzucania wskaźników.

Po prostu podkręć ostrzeżenia kompilatora - to (lub, powinien) powiedzieć, co jest niebezpieczne.

Powiązane problemy