Quero entender o seguinte código:
//...
#define _C 0x20
extern const char *_ctype_;
//...
__only_inline int iscntrl(int _c)
{
return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _C));
}
Ele se origina do arquivo ctype.h do código-fonte do sistema operacional obenbsd. Esta função verifica se um caractere é um caractere de controle ou uma letra imprimível dentro do intervalo ascii. Esta é minha corrente de pensamento atual:
- iscntrl ('a') é chamado e 'a' é convertido em seu valor inteiro
- primeiro verifique se _c é -1 e retorne 0 mais ...
- incrementar o endereço apontado pelo ponteiro indefinido em 1
- declarar esse endereço como um ponteiro para uma matriz de comprimento (caracter não assinado) ((int) 'a')
- aplique o operador bit a bit e a _C (0x20) e a matriz (???)
De alguma forma, estranhamente, ele funciona e sempre que 0 é retornado, o caractere _c não é um caractere imprimível. Caso contrário, quando estiver imprimível, a função retornará um valor inteiro que não é de interesse especial. Meu problema de compreensão está nas etapas 3, 4 (um pouco) e 5.
Obrigado por qualquer ajuda.
(unsigned char)
é cuidar da possibilidade de os personagens serem assinados e negativos.
_ctype_
é essencialmente uma matriz de máscaras de bits. Está sendo indexado pelo personagem de interesse. Assim_ctype_['A']
, conteria bits correspondentes a "alfa" e "maiúsculas",_ctype_['a']
conteria bits correspondentes a "alfa" e "minúsculas",_ctype_['1']
conteria um bit correspondente a "dígito", etc. Parece que0x20
é o bit correspondente a "controle" . Mas, por algum motivo, a_ctype_
matriz é deslocada em 1, de modo que os bits para'a'
estão realmente dentro_ctype_['a'+1]
. (Isso foi, provavelmente, para deixá-lo trabalhar paraEOF
, mesmo sem o teste extra.)