C语言sprintf的高效替代方案

C语言的sprintf和snprintf将变量格式化输出到内存buffer,其功能强大,用起来很方便。但sprintf系列函数的运行效率低下,主要包括四方面的原因:格式字符串解析、变参处理、locale(本地化)支持和通用(如对齐、填充、精度、宽度等)导致的复杂性。

在FastDFS和FastCFS开源项目中,我们将低效的sprintf和snprintf改造为高效的字符串拼接方式。因为C标准库没有提供itoa(整数转换为字符串)和ftoa(浮点数转换为字符串)这样的转换函数,我们在基础库libfastcommon中实现了fc_itoa、fc_ftoa和fc_ltostr_ex、int2hex和int2HEX等函数,这些函数均返回转换后的字符串长度。其中fc_itoa和fc_ftoa转换后的字符串不以'\0'结尾,而fc_ltostr_ex是fc_itoa的加强版,支持以'0'补齐长度,且转换后的字符串以'\0'结尾。

fc_itoa根据传入的整数大小折半查找确认输出的字符串长度,因此不需要传统的字符串逆转操作。经实测,性能大约是sprintf的6倍。

fc_ftoa支持小数点后的保留位数,和sprintf一样采用四舍五入的做法。经实测,fc_ftoa性能大约是sprintf的25倍。

int2hex转换为小写字母的十六进制字符串,而int2HEX转换为大写字母的十六进制字符串。int2hex系列函数支持前导'0'补齐,对应sprintf的格式修饰符为%0#x,其中#为对齐位数,比如 %08x。经实测,int2hex性能大约是sprintf的7倍。

为了提高替换sprintf和snprintf的代码改造效率,libfastcommon中还封装了如下函数:fc_combine_two_strings、fc_get_full_filename、fc_get_one_subdir_full_filename和fc_get_two_subdirs_full_filename等,欢迎大家观摩。

fc_itoa、fc_ftoa、fc_ltostr_ex和int2hex等转换函数在shared_func.h和shared_func.c中实现。fc_itoa、fc_ftoa、int2hex和sprintf的性能对比测试源码为 libfastcommon/src/tests/test_fast_buffer.c,感兴趣的朋友可以把玩一下。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容