Chcę zrozumieć następujący kod:
//...
#define _C 0x20
extern const char *_ctype_;
//...
__only_inline int iscntrl(int _c)
{
return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _C));
}
Pochodzi z pliku ctype.h z kodu źródłowego systemu operacyjnego obenbsd. Ta funkcja sprawdza, czy znak jest znakiem kontrolnym, czy drukowaną literą w zakresie ascii. Oto mój obecny ciąg myśli:
- Wywoływana jest funkcja iscntrl („a”), a „a” jest konwertowane na wartość całkowitą
- najpierw sprawdź, czy _c ma wartość -1, a następnie zwróć 0 w przeciwnym razie ...
- zwiększ adres niezdefiniowanego wskaźnika o 1
- zadeklaruj ten adres jako wskaźnik do tablicy o długości (znak bez znaku) ((int) „a”)
- zastosuj bitowy i operator do _C (0x20) i tablicy (???)
Co dziwne, działa i za każdym razem, gdy zwracane jest 0, dany znak _c nie jest znakiem do wydrukowania. W przeciwnym razie, gdy będzie można go wydrukować, funkcja po prostu zwraca wartość całkowitą, która nie jest przedmiotem szczególnego zainteresowania. Mój problem ze zrozumieniem znajduje się w kroku 3, 4 (trochę) i 5.
Dziękuję za wszelką pomoc.
(unsigned char)
polega na tym, aby postacie były podpisane i negatywne.
_ctype_
jest zasadniczo tablicą masek bitowych. Jest indeksowany według charakteru zainteresowania. Więc_ctype_['A']
zawierałby bity odpowiadające „alfa” i „wielkimi literami”,_ctype_['a']
zawierałby bity odpowiadające „alfa” i „małymi literami”,_ctype_['1']
zawierałby bit odpowiadający „cyfrze” itp. Wygląda na0x20
to, że jest to bit odpowiadający „kontroli” . Ale z jakiegoś powodu_ctype_
tablica jest przesunięta o 1, więc bity dla'a'
są naprawdę w_ctype_['a'+1]
. (Prawdopodobnie miało to pozwolić, aby działałoEOF
nawet bez dodatkowego testu.)