The C Programming Language(第 2 版) 笔记 / 7 输入与输出 / 7.3 变长参数表

目录、参考文献


7.3 变长参数表

本节以实现函数 printf 的一个最简单版本为例,介绍如何以可移植的方式编写可处理变长参数表的函数
因为我们的重点在于参数的处理,所以,函数 minprintf 只处理格式字符串和参数,格式转换则通过调用函数 printf 实现

函数 printf 的声明形式为 int printf(char *fmt, ...)

其中,省略号表示参数表中参数的数量和类型是可变的,省略号只能出现在参数表的尾部
因为 minprintf 函数不需要像 printf 函数一样返回实际输出的字符数,因此将它声明为 void minprintf(char *fmt, ...)

编写函数 minprintf 的关键在于如何处理一个甚至连名字都没有的参数表
标准头文件 <stdarg.h> 中包含一组宏定义,它们对如何遍历参数表进行了定义
该头文件的实现因不同的机器而不同,但提供的接口是一致的

va_list 类型用于声明一个变量,该变量将依次引用各参数
在函数 minprintf 中,将该变量称为 ap,意思是 “ 参数指针 ”
va_startap 初始化为指向第一个无名参数的指针
在使用 ap 之前,该宏必须被调用一次
参数表必须至少包括一个有名参数,va_start 将最后一个有名参数作为起点

每次调用 va_arg,该函数都将返回一个参数,并将 ap 指向下一个参数
va_arg 使用一个类型名来决定返回的对象类型、指针移动的步长
最后,必须在函数返回之前调用 va_end,以完成一些必要的清理工作

简化 printf 函数:

#include <stdarg.h>

/* minprintf: minimal printf with variable argument list */ 
void minprintf(char *fmt, ...) 
{ 
    va_list ap; /* points to each unnamed arg in turn */ 
    char *p, *sval; 
    int ival; 
    double dval; 
    va_start(ap, fmt); /* make ap point to 1st unnamed arg */ 
    for (p = fmt; *p; p++) { 
        if (*p != '%') { 
            putchar(*p); 
            continue; 
        }
        switch (*++p) { 
            case 'd': 
                ival = va_arg(ap, int); 
                printf("%d", ival); 
                break; 
            case 'f': 
                dval = va_arg(ap, double); 
                printf("%f", dval); 
                break; 
            case 's': 
                for (sval = va_arg(ap, char *); *sval; sval++) 
                    putchar(*sval); 
                break; 
            default: 
                putchar(*p); 
                break; 
        } 
    } 
    va_end(ap); /* clean up when done */ 
}

目录、参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值