2010-10-07 8 views
9

Zacząłem czytać Komentarz Lions na Unix v6. Natknąłem się na te fragmenty, których nigdy nie widziałem używane w języku C. Autor przedstawia jakieś wyjaśnienie, ale czy ktoś mógłby mi wyjaśnić, co tu się dzieje?Anonimowe struktury w C znalezione w jądrze Unix

params.h:

SW 0177570 
...... 
struct { int integ; }; 

i ten stosowany w unix/prf.c

if(SW->integ == 0) 

wyjaśnienie przez autora

SW jest zdefiniowany wcześniej jako wartość 0177570. Jest to adres jądra z tylko do odczytu rejestru procesora, który przechowuje ustawienie rejestru przełączników konsoli. Znaczenie instrukcji jest jasne: pobierz zawartość w lokalizacji 0177570 i sprawdź, czy są one zerowe. Problem polega na wyrażeniu tego w C. Kod if (SW == 0) nie przekazałby tego znaczenia. Oczywiście SW jest wartością wskaźnika, która powinna być z dereferencji. Kompilator mógł zostać zmieniony na , aby zaakceptować if (SW-> == 0) , ale w obecnej formie jest to niepoprawne składniowo. Dzięki wymyśleniu pozornej struktury, z elementem integ, programista znalazł satysfakcjonujące rozwiązanie problemu z .

Moje pytanie dotyczy głównie tego, jak to działa? Kiedy kompilator widzi SW->integ, w jaki sposób kojarzy on anonimową strukturę z SW?

Odpowiedz

6

IIRC, starsze kompilatory języka C zachowały wszystkie nazwy pól (takie jak integ) w pojedynczym obszarze nazw, zamiast tworzyć przestrzeń nazw na typ struct. Nie rozróżniono też wskaźników od struct i wskaźników int, więc każdy wskaźnik ma pole integ odpowiadające jego pierwszym bajtom . Ponieważ integ jest pierwszą wartością w struct i ma typ int, SW->integ odpowiada *((int *)SW).

+2

We współczesnym C używalibyśmy 'int * const SW = 0177570;' Ale przed pojawieniem się optymalizatorów, kosztowałoby to Kena i jego bandę kosztownymi dwoma bajtami :) –