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'表示,空白字符串使用双引号表示 ""

相关推荐
超级小星星11 小时前
C 语言结构体内存对齐深度解析:从概念到实战
c语言·开发语言
笨笨饿12 小时前
74_SysTick滴答定时器中断
c语言·开发语言·人工智能·单片机·嵌入式硬件·算法·学习方法
科芯创展12 小时前
XZ4058B/C,20V,外置MOS,8.4V/8.7V开关充电芯片 宽范围电源电压:8.9V~20V-(电池充电电压:8.4V/8.7V)
c语言·开发语言
Aurorar0rua13 小时前
CS50 x 2024 Notes C -11
c语言·开发语言·学习方法
Dlrb121113 小时前
C语言-指针
c语言·开发语言
12.=0.15 小时前
【stm32_9.2】FreeRTOS的任务管理:任务策略,调度器启用,任务创建、删除、挂起、恢复
c语言·stm32·单片机·嵌入式硬件
谙弆悕博士16 小时前
【附C源码】二叉搜索树的C语言实现
c语言·开发语言·数据结构·算法·二叉树·项目实战·数据结构与算法
开发者联盟league17 小时前
在cursor中配置c/c++开发环境
c语言·开发语言·c++
『昊纸』℃17 小时前
C语言简介
c语言·操作系统·编程语言·应用领域·历史发展
刃神太酷啦18 小时前
《网络基础全链路深度解析:从Socket编程到HTTPS与TCP/UDP内核机制》----《Hello Linux!》(25)
linux·运维·c语言·网络·c++·tcp/ip·https