I want to understand the following code:
//...
#define _C 0x20
extern const char *_ctype_;
//...
__only_inline int iscntrl(int _c)
{
return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _C));
}
It originates from the file ctype.h from the obenbsd operating system source code. This function checks if a char is a control character or a printable letter inside the ascii range. This is my current chain of thought:
- iscntrl('a') is called and 'a' is converted to it's integer value
- first check if _c is -1 then return 0 else...
- increment the adress the undefined pointer points to by 1
- declare this adress as a pointer to an array of length (unsigned char)((int)'a')
- apply the bitwise and operator to _C (0x20) and the array (???)
Somehow, strangely, it works and everytime when 0 is returned the given char _c is not a printable character. Otherwise when it's printable the function just returns an integer value that's not of any special interest. My problem of understanding is in step 3, 4 (a bit) and 5.
Thank you for any help.
_ctype_
is essentially an array of bitmasks. It's being indexed by the character of interest. So_ctype_['A']
would contain bits corresponding to "alpha" and "uppercase",_ctype_['a']
would contain bits corresponding to "alpha" and "lowercase",_ctype_['1']
would contain a bit corresponding to "digit", etc. It looks like0x20
is the bit corresponding to "control". But for some reason the_ctype_
array is offset by 1, so the bits for'a'
are really in_ctype_['a'+1]
. (That was probably to let it work forEOF
even without the extra test.) – Trouveur(unsigned char)
is to take care of the possibility that characters are signed and negative. – Trouveur