Я хочу понять следующий код:
//...
#define _C 0x20
extern const char *_ctype_;
//...
__only_inline int iscntrl(int _c)
{
return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _C));
}
Он происходит из файла ctype.h из исходного кода операционной системы obenbsd. Эта функция проверяет, является ли символ контрольным символом или печатной буквой в диапазоне ASCII. Это моя нынешняя цепочка мыслей:
- iscntrl ('a') вызывается и 'a' преобразуется в его целочисленное значение
- сначала проверьте, является ли _c -1, затем верните 0, иначе ...
- увеличить адрес, на который указывает неопределенный указатель, на 1
- объявить этот адрес как указатель на массив длины (без знака) ((int) 'a')
- применить побитовый и оператор к _C (0x20) и массиву (???)
Каким-то странным образом это работает, и каждый раз, когда возвращается 0, данный символ _c не является печатным символом. В противном случае, когда она печатается, функция просто возвращает целочисленное значение, которое не представляет особого интереса. Моя проблема понимания заключается в шаге 3, 4 (немного) и 5.
Спасибо за любую помощь.
(unsigned char)
должен позаботиться о том, чтобы символы были подписаны и отрицательные.
_ctype_
по сути, это массив битовых масок. Это индексируется по характеру интереса. Таким образом,_ctype_['A']
будет содержать биты, соответствующие «альфе» и «верхнему регистру»,_ctype_['a']
будет содержать биты, соответствующие «альфе» и «нижнему регистру»,_ctype_['1']
будет содержать бит, соответствующий «цифре» и т. Д. Похоже,0x20
это бит, соответствующий «управлению» , Но по какой-то причине_ctype_
массив смещен на 1, поэтому биты для'a'
действительно в_ctype_['a'+1]
. (Это должно было позволить ему работатьEOF
даже без дополнительного теста.)