<stdarg.h> 省略号的使用

<stdarg.h>

//argument 自变量(函数)
//用于面向用户的函数(自行输入)
//是一个链表,设计的很好的链表

给函数输入参数时,需要设定参数个数和类型;
使用结构体作为输入参数时,也需要给结构体赋值;
所以,有没有办法进行 任意类型 任意数量 的参数输入呢?
在C的标准库函数中,提供了<stdarg.h>的头文件
载入后便可以使用C中的省略号'...',进行宽泛的输入

使用

对于文件使用->标识符/打开/使用/关闭
标识符->FILE *fd;
打开->fd=fopen();
使用->fread/fwrite(fd);
关闭->fclose(fd);

对于省略号也同样如此
//作用:多数相加
int my_add(int num,...){};//省略号//必须是 , + ...

va_list mytab;//标识符
va_start(arg_ptr,num);//开始//不用赋值
va_arg(arg_ptr,int);//使用//以 int类型 读取
va_end(arg_ptr);//结束

函数定义
va_list//适用va_start/arg/end函数存储信息的类型
void va_start(va_list ap, last_arg)//last_arg函数的最后一个固定参数
type va_arg(va_list ap, type)//type 输出的类型
void va_end(va_list ap)

例子:

//1.int类型 未定数量 的加法函数
//number=my_add(1,2,3,4,5,0);//number=15
int my_add(int num,...){
    int sum=0;
    sum+=num;

    va_list arg_ptr;
    int num_s;

    va_start(arg_ptr,num);
    do{
        num_s=va_arg(arg_ptr,int);
        sum+=num_s;
    }while(num_s != 0);//输入0 则退出
    va_end(arg_ptr);

    return sum;
}

//2.printf()的实现
//一个链表构成的栈
static char sprint_buf[2408];
 
int printf(const char *fmt, ...)
{
    va_list args;
    int n;
    // 第一个可变形参指针
    va_start(args, fmt);
    // 根据字符串fmt,将对应形参转换为字符串,并组合成新的字符串存储在sprint_buf[]缓存中,返回字符个数。
    n = vsprintf(sprint_buf, fmt, args);
    //c标准要求在同一个函数中va_start 和va_end 要配对的出现。
    va_end(args);
    // 调用相关驱动接口,将将sprintf_buf中的内容输出n个字节到设备,
    // 此处可以是串口、控制台、Telnet等,在嵌入式开发中可以灵活挂接
    if (console_ops.write)
        console_ops.write(sprint_buf, n);
    return n;
}


原理

C语言Printf函数深入解析

在<stdarg.h>文件中,定义了变量类型 va_list 和三个宏
这三个宏可用于在参数个数未知(即参数个数可变)时获取函数中的参数
可变参数的函数通在参数列表的末尾是使用省略号(,...)定义的

typedef char *va_list;
typedef int acpi_native_int;

//入栈4字节对齐//出栈4字节对齐// 4字节对齐
#define  _AUPBND                (sizeof (acpi_native_int) - 1)
#define  _ADNBND                (sizeof (acpi_native_int) - 1)
#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))

//第一个可变形参指针
#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

//按照4字节对齐取下一个可变参数,并且更新参数指针
#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) 

//与va_start成对,避免有些编译器告警
#define va_end(ap)              (void) 0//结束,清空链表

学习引用:
部分基础概念
stdarg.h头文件源代码分析

posted @   night000day  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示