Do you know ? 函数的参数数目可变化大小!!!

来源:互联网 发布:协同过滤算法java代码 编辑:程序博客网 时间:2024/05/20 03:45

可变参数列别解析

前言很多朋友都不清楚c语言中关于函数还有一个很有意思的东西——“可变参数列表”。那么本主今天就借助模拟实现printf()函数的例子给大家说道说道关于“函数可变参数列表”的事情!

例码:print()函数

#include<stdio.h>#include<stdarg.h>void display(int n)//打印n的每一位,例如:n = 123 将打印出 1 2 3{    if (n > 9)    {        display(n/10);    }    putchar((n % 10) + '0');}void print(char *format, ...){    va_list arg;    va_start(arg, format);    char tmp;    while ((tmp = *format ) != '\0')    {        format++;        switch (tmp)        {        case 's'://如果字符串内字符为 'S',将执行字符串打印工作                {                    char *ret = va_arg(arg, char *);                    while (*ret != '\0')//字符串打印工作                    {                        putchar(*ret);                        ret++;                    }                }            break;        case 'c'://如果字符串内字符为 'C',将执行字符打印工作                {                    char ret = va_arg(arg, char);                    putchar(ret);//字符打印工作                }            break;        case 'd'://如果字符串内字符为 'd',将执行整形数值(十进制)打印工作                {                    int ret = va_arg(arg, int);                    display(ret); //执行整形数值(十进制)打印工作                }            break;        default:            putchar(tmp);//否则,原样输出            break;        }    }}int main(){    print("s ccc d%.\n", "hello", 'b', 'i', 't',100);    return 0;}

说明:

  • 我们必须要清楚函数调用时形参实例化的过程,参数是“从右向左”依次入栈的。如下图:
    这里写图片描述
  • void print(char *format, ...)参数列表后面的“ …”表示参数个数不固定。
  • 可变参数必须从头到尾依次访问,不可跳转访问,当然,如果你在访问几个参数后不想继续访问后边的参数也是可以的。
  • 可变参数列表前面必须至少有一个命名参数,否则,将不能使用va_start进行初始化。
  • 函数实现中使用的va_*系列宏无法直接判断可变参数个数、每个参数类型。
  • 在使用va_arg时,如果指定了错误的类型,那么后果将非常严重“一步失足,满盘皆输”。

正文:

调用print("s ccc d%.\n", "hello", 'b', 'i', 't',100);参数实例化过程如下图:

这里写图片描述

详解:_INTSIZEOF(n)

这里写图片描述

详解:va_*系列宏

这里写图片描述

详解:print()函数

这里写图片描述

总结:

  • 函数的可变参数列表的实现是借助参数“命名参数部分”的最后一个命名参数的地址偏移进而找到“可变参数部分第一个参数的地址”进而往后访问其它可变参数部分。
0 0