sprintf的实现与stdarg的可能实现

C/C++

Posted by Bruce Lee on 2024-07-13

关于我

欢迎来到我的博客!这里汇集了我对编程和技术的洞见和总结。本站内容分为几个主要类别,涵盖从具体技术实现到编程理念的广泛话题。

主要内容分类

  • 项目工程:深入探讨技术的实现细节和理解。
  • C/C++:围绕C/C++语言的技术点和编程技巧进行详细总结。
  • 程序员哲学:分享程序员在职业生涯中应该具备的哲学理念和思考方式。

想要了解更多具体内容,您可以访问文章分类页面。

联系我

如果您有任何问题或想要交流,欢迎通过关于页面与我联系。

感谢您的阅读和支持,希望我的博客能为您的技术旅程带来帮助!


sprintf的实现与stdarg的可能实现

使用stdarg来实现函数的变参.

stdarg可能实现

对于va_list, 这必然是一个指针,用于指示下一个变量的地址.

va_start这个宏,传入了两个参数,一个是args,一个是最后一个固定参数.

知道了最后一个固定参数,便可以根据固定参数的位置和其大小,使args指向下一个参数位置.

va_arg宏也是传入两个参数,一个是args,一个是读取的参数的大小.

一是因为,必须有一个读取参数的大小的概念,然后读取出来,并且将args指向下一个.

二是因为,这样好读取出正确的位数.

没有黑魔法,突然就识别出参数了.

传参的时候,如何做到结束.

根据模式字符串中的标识符,来检索变参args中的数量,以及是否还有继续读取va_arg中的返回值

在%d中的数字转换

由于没有itoa函数,我自己实现了一个itoa_special函数,这个函数的功能是特制的:将数字num插入一个字符串的指定位置,这个指定位置由iterator来决定.

其中"细数"了负数,0的处理

并且返回了迭代器的值.

sprintf的剩余情况

为何sprintf的第二个参数是const char*

因为是为了根据fmt的字符,然后将字母挨个写入out,而不是修改fmt的内容,然后将fmt拷贝到out.

sprintf的主要策略:
循环处理fmt中的每一个字符
普通字符直接拷贝到str中
遇见百分号,直接进入switch处理代码块
遇见噪声:%m之类的,那么直接将%到这个字母的所有都拷贝过去.
注意不同变量的迭代情况

读取char型数据的时候,出现了promoted警告.

这是因为所有的char,short,float在经过变参系统提取出来的时候,都是经过了扩展,变成了,int,double.

所以如果以char tmp = va_arg(args, char);来读取的时候,便会报错.

只能这样:char tmp = (char)va_arg(args, int);


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. All the images used in the blog are my original works or AI works, if you want to take it,don't hesitate. Thank you !