Я хочу зрозуміти наступний код:
//...
#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 else ...
- приріст адреси на невизначений покажчик вказує на 1
- оголосити цю адресу як вказівник на масив довжини (неподписаний знак) ((int) 'a')
- застосувати побітові та оператор до _C (0x20) та масиву (???)
Якимось чином, як не дивно, він працює і кожного разу, коли 0 повертається, даний char _c не є символом для друку. Інакше при друкуванні функція просто повертає ціле значення, яке не представляє особливого інтересу. Моя проблема розуміння полягає в кроці 3, 4 (трохи) та 5.
Дякую за будь-яку допомогу.
(unsigned char)
належить піклуватися про можливість підписання символів та негативів.
_ctype_
по суті є масивом бітових масок. Він індексується характером, що цікавить. Таким чином ,_ctype_['A']
буде містити біти , що відповідають «альфа» і «великі букви»,_ctype_['a']
буде містити біти , що відповідають «альфа» і «нижній регістр»,_ctype_['1']
буде містити біт , відповідне «цифру», і т.д. Схоже ,0x20
це біт , відповідні «контроль» . Але чомусь_ctype_
масив компенсується на 1, тому біти для'a'
насправді є_ctype_['a'+1]
. (Це, мабуть, дозволило йому працюватиEOF
навіть без зайвих випробувань.)