2017-07-16 21 views
8

To jest moje zrozumienie, że coś takiego jest w porządku:Czy to jest w porządku dla int ** i const int ** dla aliasu?

const int ci = 42; 
const int *cip = &ci; 
int *ip = (int *)cip; 
int j = *ip; 

Co na ten temat?

const int ci = 42; 
const int *cip = &ci; 
const int **cipp = &cip; 
int **ipp = (int **)cipp; 
int j = **ipp; 
+0

'int * ip = (int *) cip;' nie jest OK. Twój kompilator powinien narzekać na zrzucenie 'const'. Jeśli nie, użyj wyższych poziomów ostrzegawczych. Albo o jakim "OK" myślisz? "działa", "działa niezawodnie", "działa przenośnie", "jest dobrym kodem", ... – Yunnosch

+7

@Yunnosch: Nie. Jest całkowicie OK. Wyraźna obsada jest tak naprawdę, jak * możesz * powiedzieć * kompilatorowi, że * naprawdę chcesz * pozbyć się 'const'. W ten sposób mówisz kompilatorowi, aby nie wysyłał żadnych ostrzeżeń.Pierwszy fragment kodu jest całkowicie legalny C. – AnT

+0

@AnT Dla pokazanego kodu, pozbycie się stałej nie jest potrzebne. Dla innego kodu tracenie stałej, która ma cel, nie jest dobrym pomysłem. Przyznaję jednak, że myliłem ostrzeżenia kompilatora z rodzajami ostrygowych ostrzeżeń generowanych przez wyjątkowo dokładne analizatory statycznych kodów; które mam użyć dla kodu w pracy. Potrzebują więcej niż obsady, by przestać dokuczać. To jest trochę spalone w moim myśleniu. – Yunnosch

Odpowiedz

5

Wyrażenie *ipp jest lwartością typu int *, jednak jest używany do uzyskania dostępu do obiektu skuteczny rodzaj const int *. (Mianowicie, cip).

Zgodnie z literą standardu, jest to naruszenie ścisłego aliasingu: lista dozwolonych typów do aliasu nie obejmuje aliasowania T * jako const T * lub odwrotnie.

gdzie znajduje wyjątku jest taka: (C11 6,5/6 fragment)

  • wykwalifikowanego wersji typu zgodnego z efektywnym typu obiektu

„jakości wersja "jest jasno zdefiniowana przez C11 6.2.5/26:

Każda niewykwalifikowany typu ma kilka wykwalifikowanych wersje tego typu, odpowiednio do połączenia jednego, dwóch lub wszystkich trzech const, volatile i restrict kwalifikacjach. Kwalifikowane lub niewykwalifikowane wersje typu są różnymi typami, które należą do tej samej kategorii typów i mają takie same wymagania dotyczące odwzorowania i wyrównania. Typ wyprowadzony nie jest kwalifikowany przez kwalifikatory (jeśli istnieją) typu, z którego pochodzi.

Więc Wyjątkiem jest to, że może być aliasem T jak const T i odwrotnie, ale nie ma podobny wyjątek dla wskaźniki do aliasable typów. const T * nie jest kwalifikowaną wersją z T *.


Jednak nie jest oczywiście przypis:

Celem tej listy jest określenie tych okoliczności, w których przedmiotem może być lub nie być aliasem

Nie mogłem t powiedzieć, czy intencją reguły sąi T * aliasowalne, czy też nie. Wydaje mi się niejasne, jaki jest cel określenia, że ​​T * i const T * mają "takie same wymagania odwzorowania i wyrównania" (6.2.5/28), jeśli nie można ich używać jako zmiennych.

+1

Fakt, że gwarancja byłaby użyteczna tylko wtedy, gdyby był traktowany jako wyjątek od zasad aliasingu, nie oznacza już, że twórcy kompilatorów zinterpretują to jako jeden. Gwarancje Common Initial Sequence są w zasadzie bezużyteczne w gcc i clang, z wyjątkiem trybu "no strict aliasing". Jak już wspomniano, żaden kompilator * jeszcze * nie zakłada, że ​​'int * p' nie będzie dostępne za pomocą' int const ** p', ani na odwrót; Nie wiem, czy to pozostanie prawdą. – supercat

Powiązane problemy