变参函数与简版printf函数的实现

变参函数

  • 形如int max_int(int a, …);参数列表中含有变参列表“…”(这不是省略号),a是…变参列表中参数的个数
  • 变参列表的实现是借助va一族:
“函数”功能
va_list获得a往后的参数列表
va_start定位a后面第一个参数的位置
va_arg获取下一个可变参数列表中的参数
va_end销毁list,结束整个获取可变参数列表的动作
  • 以上不是严格意义上的函数,因为以上函数把类型当作形参,而这个功能函数是无法实现的,只能借助宏定义来完成
  • 头文件:stdarg.h

变参函数的应用

求一系列数字的最大值

#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#define INT32_MIN -pow(2, 31)
#define INT32_MAX pow(2, 31) - 1

int max_int(int n, ...) {
    int ans = INT32_MIN;
    va_list arg;
    va_start(arg, n);
    while (n--) {
        int temp = va_arg(arg, int);
        if (temp > ans) ans = temp;
    }
    va_end(arg);
    return ans;
}

int main() {
    printf("%d\n", max_int(3, 1, 2, 3));
    printf("%d\n", max_int(5, 1, 2, 3, 24, -1));
    return 0;
}

运行结果:
在这里插入图片描述

  • 在第12行va_arg(arg, int)若变参列表的参数分别是char a, int b, double c则根据这个“函数”的功能只能取到b
  • inttypes.h头文件下的宏定义INT32_MIN和INT32_MAX在我的编译器上(CodeBlocks)没反应,还没搞清楚有没有这俩玩意儿
  • 上面的代码体现读取变参列表的过程:创建list→取第一个形参的地址→获取变参列表中下一个形参→销毁list,最后一步是一个习惯,就像创建指针最后要销毁指针一样

自制printf函数

  • printf底层是用putchar()一个一个打印字符实现的,输出流cin是用printf来实现的,因此自制printf函数中用putchar()来实现
  • 以下是简单输出字符串
#include <stdio.h>
//#include <stdarg.h>
#include <string.h>

int my_printf(const char *frm, ...) {
    int cnt = 0;
    for (int i = 0; i < strlen(frm); i++) {
        putchar(frm[i]), cnt++;
    }
    return cnt;
}

int main() {
    my_printf("Hello world\n");
    return 0;
}

在这里插入图片描述

  • 那么要输出整型变量:
#include <stdio.h>
#include <stdarg.h>
//#include <string.h>

int my_printf(const char *frm, ...) {
    int cnt = 0;
    va_list arg;
    va_start(arg, frm);
    #define PUTC(a) putchar(a), cnt++
    for (int i = 0; frm[i]; i++) {
        switch (frm[i]) {
            case '%': {
                switch (frm[++i]){
                    case '%':
                        PUTC(frm[i]);
                        break;
                    case 'd': {
                        int x = va_arg(arg, int);
                        char num[16] = {0};
                        int k = 0;
                        while (x) {
                            num[k++] = x % 10 + '0';
                            x /= 10;
                        }
                        while (k > 0) {
                            PUTC(num[--k]);
                        }
                    }break;
                }
            }break;
            default:
                PUTC(frm[i]);
        }
    }
    return cnt;
}

int main() {
    int a = 123;
    my_printf("Hello world\n");
    my_printf("%%%d", a);
    return 0;
}

在这里插入图片描述

  • 上面的代码只是一个简易版的printf函数,整数的输出可能还有一些bug,当然了,最重要的是深入理解printf的底层实现过程!
  • 同理scanf函数的简易实现是借助getchar()来完成的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值