ptintf函数的简单实现(可变参数列表)

在我们写过以往的代码中频繁使用printf函数,printf函数在传参过程中其参数其实是不固定的

printf("hello world\n");//1个参数
printf("%s", "hello world\n");//2个参数
printf("%s %s","hello","world\n");//3个参数

我们可以通过以下简单的代码来分析可变参数列表

#include <stdio.h>
#include <stdarg.h>
int Average(int n, ...)
{
    va_list arg;
    int i = 0;
    int sum = 0;
    va_start(arg, n);
    for (i=0; i<n; i++)
    {
        sum += va_arg(arg, int);
    }
    return sum/n;
    va_end(arg);
}

int main()
{
    int ret = 0;
    ret = Average(3, 1, 2, 3);
    printf("%d\n", ret);
    ret = Average(4, 5, 6, 7, 8);
    printf("%d\n", ret);
    return 0;
}

上面代码中几个陌生的点(实现可变参数):

  • 声明一个va_lisi类型的变量arg,它用于访问参数别表未确定的部分

  • va_start用于初始化变量arg。它的第一个参数是va_lisi的变量名,第二个参数是省略号前最后一个有名字的参数。初始化过程把arg变量设置为指向可变参数部分的第一个参数。

  • va_arg用于访问参数,此宏接受两个参数:va_list变量和参数列表中下一个参数的类型。va_arg返回这个参数的值,并使用va-arg指向下一个可变参数。实现此功能的代码非常经典,值得学习(在此代码中宏替换后的结果):

( *(int *)((arg += 4) - 4) )
  • va_end使使用完后的指针变量赋成空指针。
    这里写图片描述
    可见:可变参数的实现过程实际上是使用宏进行封装,只要完成替换便一目了然

    上面代码的运算结果:
    这里写图片描述

    分析完成这一段代码,就可以对printf函数进行简单的模拟
    printf函数并没有直接的给出可变参数列表的参数个数,但是它在第一个字符串的内部,通过输出格式间接给出了这个个数,所以如果要拿到这个值,必须对第一个字符串进行解析

    • 如果是整形按照递归的写法拿出这个整形的每一位,并用putchar函数以其对应的字符输出
    • 如果是字符串,循环遍历整个字符串,并用putchar输出每一个字符,遇到'\0'停止
    • 如果是字符直接putchar输出
    代码如下:
#include <stdarg.h>

void show(int n)
{
    if(n>9)
    {
        show(n/10);
    }
    putchar(n%10+'0');
}

void print(const char *format, ...)
{
    va_list arg;
    va_start(arg, format);
    while(*format)
    {
        switch(*format)
        {
        case 's':
            {
                char *ret = va_arg(arg, char*);
                while(*ret)
                {
                    putchar(*ret);
                    ret++;
                }
            }
            break;
        case 'd':
            {
                int ret = va_arg(arg, int);
                show(ret);
            }
            break;
        case 'c':
            {
                int ch = va_arg(arg, char);
                putchar(ch);
            }
            break;
        default:
            putchar(*format);
            break;
        }
        format++;
    }
}

int main()
{
    print("d s c\n", 100, "hehe", 'w');
    return 0;
}

运算结果:
这里写图片描述
当然库函数中的printf函数实现远比这复杂的多,有待于今后的进一步研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值