引言
_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中的函数,将一个整型数据转换为对应进制的字符串数据,主要是调用了除数取余法实现。