_fitoa_word 的实现:一个整型数据是如何转成字符串的呢?
引言
_fitoa_word 是一个将 int 型数据转换为对应进制的 char 类型的函数,在通常的整型数据处理中非常常见,用来打印一个整型数据对应的 N 进制表示,对于其原理,实际上就是我们中学时候学习的除数取余法,然后再选取对应的符号进行表示。那么在 Glibc 源码中,它又是如何实现的呢?接下来,我们一起来看看对应的实现。
函数定义
参考代码:glibc/sysdeps/generic/_itoa.h
其中:
入参
_ITOA_WORD_TYPE value:是本次需要转换的整型量,_ITOA_WORD_TYPE 被定义为
#define _ITOA_WORD_TYPE unsigned long int
,即 64 位系统下 8 个字节大小的整型变量char *buf:本次的输出字符串开始指针
unsigned int base:进制
int upper_case:标识是否需要大写(如 0xf 与 0XF)
出参
char *:标识最后一个写入 buf 的字符的指针的下一个位置
函数实现
代码位置:glibc/stdio-common/_itoa.c
_fitoa_word 逻辑
可以看到,这里的实现实际上还是转交给到了_itoa_word 函数,但是在_fitoa_word 中也做了如下的处理:
申请临时 buffer tmpbuf,用于_fitoa_word 的生成字符串;
注意:这里选择的 buffer 大小 sizeof (value) * 4,考虑到我们进行进制转换时,相同的整型数据,越高的进制生成的字符串越短,所以最坏的情况就是二进制全部用 01 进行填充,那就应该是有多少位,每个字节 8 位,所以是 sizeof (value) * 8,但这里是*4。
调用_itoa_word;
依次将转换后的字符串拷贝到 buf 中,后置递增运算符是先使用当前值,然后再递增。
_itoa_word 函数参数
与_fitoa_word 基本一致,但要注意,这里的 char *buflim 指向的是分配的临时 buffer 的最后一个可写位置的下一个地址:tmpbuf + sizeof (value) * 4
_itoa_word 函数逻辑
1.根据 upper_case 选择对应的字符集
根据是否需要大写选择对应的字符集,_itoa_upper_digits 或 _itoa_lower_digits。
2.使用除数取余法进行进制转换
注意,这里定义了一个宏 SPECIAL(Base),针对我们常用的 10 进制、16 进制、8 进制做了简化,但实际逻辑还是与 default 的一致。
先对 value 使用 %取余数,得到对应的符号;
注意--buflim 是先做递减运算,再使用该值,第一次递减则刚好是上面 tmpbuf 的最后一个位置;
使用*取地址并进行赋值;
对 value 做除法,直到除数为 0,否则重复上面的步骤。
上面就是一个标准的除数取余法。
3.返回 buflim 指针
注意,这里返回的 buflim 实际上最后指向的是第一个字符;
然后 undef SPECIAL,避免后续使用出现覆盖异常
总结
_fitoa_word 函数是 Glibc 中的函数,将一个整型数据转换为对应进制的字符串数据,主要是调用了除数取余法实现。
版权声明: 本文为 InfoQ 作者【桑榆】的原创文章。
原文链接:【http://xie.infoq.cn/article/9db932c3390b1db58b6256aa5】。文章转载请联系作者。
评论