c语言中为函数输入可变长的参数

今天在《征服C指针》的书里面看到了一个很有意思的函数写法。即写一个输入的参数数量是可变的。

一个典型的可变输入函数就是printf(),该函数根据解析字符串中的%s, %d,%p等,就可以知道后面带有多少个参数。

但实际上,由于c语言数据的压栈方式,我们只需要知道第一个参数的位置,后续的参数就可以按顺序读取。也就是说我们要做的就是告诉函数,参数的起止,以及参数的格式,让函数能正确地读取参数。

ANSI C通过头文件stdarg.h提供了一组可用于可变参数的宏。代码如下。

c 复制代码
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

void tiny_printf(char *format, ...)
{
    int i;
    va_list ap;

    va_start(ap, format);

    for(i = 0; format[i] != '\0'; i++)
    {
        switch (format[i])
        {
            case 's':
                /* code */
                printf("%s ", va_arg(ap, char*));
                break;
            case 'd':
                /* code */
                printf("%d ", va_arg(ap, int));
                break;
            
            default:
                assert(0);
        }
    }
    va_end(ap);
    putchar('\n');
}
int main(void)
{
    tiny_printf("ssdd", "hu", "cong", 6, 6);
    return 0;
}

注意到上述的代码,输入处的"..."代表着输入处不用进行参数的检查。

其中声明了va_list 类型的变量,可以看作某种指针,va_start(ap, format);代表将ap指向format后面的下一参数的位置,然后在循环中每次调用va_arg都会指向下一个参数,然后通过format中的指示,告诉我们第几个参数是哪种格式,就能正确地读取参数。比如上述代码中"ssdd"代表第一个和第二个是字符串,三个和第四个是整型。如此可依次取出所有参数。

va_end是对应于va_start的函数,在可变长参数的传递过程中,由va_start分配内存并将参数保存其中,最后由va_end释放内存。

输出结果如下:

复制代码
hu cong 6 6 

注意:代码中出现了许多单引号和双引号,很多时候他们并不能相互替换,因为其表示的含义不同。

'A' 表示单个字符大写字母A,占用1个字节空间

"A" 表示字符串,该字符串只有1个大写字母A组成,占用2个字节空间,每个字符串末尾自动会加上一个空字符 '\0'

空字符常量使用转义符号 '\0'表示,空白字符串使用双引号表示 ""

相关推荐
小马学嵌入式~24 分钟前
嵌入式 SQLite 数据库开发笔记
linux·c语言·数据库·笔记·sql·学习·sqlite
青 .1 小时前
数据结构---二叉搜索树的实现
c语言·网络·数据结构·算法·链表
MChine慕青2 小时前
顺序表与单链表:核心原理与实战应用
linux·c语言·开发语言·数据结构·c++·算法·链表
云:鸢4 小时前
C语言链表设计及应用
c语言·开发语言·数据结构·链表
正在起飞的蜗牛6 小时前
【C语言】函数指针的使用分析:回调、代码逻辑优化、代码架构分层
c语言·架构
饭碗的彼岸one6 小时前
C++ 并发编程:异步任务
c语言·开发语言·c++·后端·c·异步
水饺编程7 小时前
Windows 命令行:cd 命令3,当前目录,父目录,根目录
c语言·c++·windows·visual studio
kyle~7 小时前
C/C++---动态内存管理(new delete)
c语言·开发语言·c++
Yuki’8 小时前
网络编程---UDP
c语言·网络·网络协议·udp
.YM.Z9 小时前
C语言——文件操作
c语言·文件操作