【发布时间】:2016-10-08 17:13:41
【问题描述】:
我试图理解一段使用__ctype_b_loc()的代码,问题是我不知道这个函数的目的是什么。
到目前为止,我发现它是在ctype.h 中定义的。我还找到了它的原型和实现。我仍然不知道这个函数是干什么用的。
谁能启发我?
【问题讨论】:
我试图理解一段使用__ctype_b_loc()的代码,问题是我不知道这个函数的目的是什么。
到目前为止,我发现它是在ctype.h 中定义的。我还找到了它的原型和实现。我仍然不知道这个函数是干什么用的。
谁能启发我?
【问题讨论】:
经过公平的研究,我想我可以回答自己这个问题。
unsigned short int** __ctype_b_loc (void)是一个函数,它返回一个指向“traits”表的指针,该表包含一些与每个单个字符的特征相关的标志。
这是带有标志的枚举:
ctype.h
enum
{
_ISupper = _ISbit (0), /* UPPERCASE. */
_ISlower = _ISbit (1), /* lowercase. */
_ISalpha = _ISbit (2), /* Alphabetic. */
_ISdigit = _ISbit (3), /* Numeric. */
_ISxdigit = _ISbit (4), /* Hexadecimal numeric. */
_ISspace = _ISbit (5), /* Whitespace. */
_ISprint = _ISbit (6), /* Printing. */
_ISgraph = _ISbit (7), /* Graphical. */
_ISblank = _ISbit (8), /* Blank (usually SPC and TAB). */
_IScntrl = _ISbit (9), /* Control character. */
_ISpunct = _ISbit (10), /* Punctuation. */
_ISalnum = _ISbit (11) /* Alphanumeric. */
};
举个例子,如果你查找表__ctype_b_loc()返回ascii代码为0x30('0')的字符,你将得到0x08d8。
0x08d8=0000 1000 1101 1000 (Alphanumeric, Graphical, Printing, Hexadecimal, Numeric)
该表与机器上安装的语言环境的localchar 相关联,因此与您系统上的结果相比,该示例可能不准确。
【讨论】:
Alessandro 自己的回答内容丰富,但我想补充一些信息。
正如 Alessandro 所说,__ctype_b_loc(void) 函数返回一个数组,其中每个元素都包含一个 ASCII 字符的特征。例如,通过查表,我们可以知道字符“A”是大写、十六进制、图形、印刷、字母数字。
准确地说,__ctype_b_loc() 函数返回一个 const unsigned short int**,它是一个指向 384 个数组的指针 unsigned short int*。
有 ara 384 个元素的原因是该表可以通过以下方式索引:
unsigned char 值 [0,255](所以 256 个元素)signed char 值 [-128,-1)(所以 127 个元素)此表由函数使用:
但是,这些函数被定义为宏,因此您永远不会看到它们在汇编代码中被调用。您将看到调用__ctype_b_loc() 来获取表、一些用于检索正确条目的代码以及使用位掩码来查看我们正在检查的属性是否已设置。例如,如果我们想查看一个字符是否为大写,我们必须检查是否设置了位 0。
这里是调用isupper('A');生成的汇编代码:
call sym.imp.__ctype_b_loc ; isupper('A');
mov rax, qword [rax] ; get the pointer to the array of 'unsigned short int*'
movsx rdx, byte 0x41 ; prepare to look up for character 'A'
add rdx, rdx ; each entry is 2 bytes, so we double the value of 'A'
add rax, rdx ; look up for 'A' in the table
movzx eax, word [rax] ; get the 'unsigned short int' containing the properties
movzx eax, ax
and eax, 0x100 ; 0x0100 in little-endian is 0x0001 in big-endian (check if bit 0 is set)
【讨论】: