可变參数列表

在函数原型中。列出了函数期望接受的參数,但原型仅仅能显示固定数目的參数。让一个函数在不同的时候接受不同数目的參数是不是能够呢?答案是肯定的,但存在一些限制。

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>

//利用可变參数列表实现加法。

int add(int num, ...) { int i = 0; int sum = 0; int tmp = 0; va_list arg;//在这定义了一个char 类型的指针。 va_start(arg, num);//这个的功能是读取全部的參数。从头開始 //后读取你所给的參数个数,而且把參数放到指针中。 for (i = 0; i < num; i++) { tmp = va_arg(arg, int);//在这,起到的作用是读取所给的參数 sum += tmp; } va_end(arg);//结束读取 return sum; } int main() { int ret = 0; ret=add(4,5,6,7,5); printf("%d", ret); system("pause"); return 0; }

这里写图片描写叙述

要记住以下这些都封装在stdarg.h头文件里。
va_list arg这个说的就是一个char 类型的指针,而且记住地址
va_start(arg,…之前的一个參数) 读取全部的參数,从头開始后读取你所给的參数个数。而且把參数放到指针中。
va_arg (arg,类型)读取參数,挨个读取。返回这个參数的值,而且使得指向下一个可变參数。


va_end(arg) 结束读取。

*C语言中对可变參数的限制

-无法确定可变參数列表的长度。
-不能提供类型检查。

对于关键的宏进行解读

  • 1.va_list
    宏:#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    这个宏本身仅仅是个定义,真正赋予其意义的在于以下的几个宏。
    实现:实际上仅仅是一个 char * 类型的指针,原因这里不能判定类型。所以用size为1的char类型指针会方便移动。

  • 2.va_start
    宏:#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
    这个宏须要两个參数,第一个是上面定义的 va_list。 第二个是可变參数列表之前的那个參数。


    注意:va_start中的參数,一定要是最后一个參数,也就是…之前的那个參数,不然可能会有问题。尤其是windows和linux的函数參数入栈顺序不同。会有可移植性问题。

  • 3.va_arg
    宏:#define va_arg(ap,t) ( (t )((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
    相同有两个參数。第一个是前面已经初始化好的 va_list,第二个是类型。比方这里可变參数列表的第一个參数是int类型,那么就传int。

  • 4.va_end
    宏:#define va_end(ap) ( ap = (va_list)0 )
    为了更好的可读性,结束可变參数的获取。

可变參数必须从头到尾依照顺序逐个进行訪问。假设你在訪问几个可变參数后想半途中止,这是能够的,可是不能一開始就訪问參数列表中间的參数。

另外须要注意的是。參数列表中至少须要有一个命名參数。命名參数指定了实际传递的參数数量,
接下来,来用可变參数列表实现一个超级厉害的system函数。

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
#include<string.h>
void go(int num, ...)
{
    int i = 0;
    va_list arg;
    va_start(arg, num);
    for (i = 0; i < num; i++)
    {
        char arr[20];
        strcpy(arr, va_arg(arg, char *));
        printf("%s", arr);
        system(arr);
    }
    va_end(arg);
}
int main()
{
    go(9,"notepad","calc","tasklist","ipconfig","mspaint","write","title wuyuzhe","color 3e","pause");
}

这里写图片描写叙述
这里写图片描写叙述
这里写图片描写叙述

在这里通过这个超级厉害的system函数能够实现打开记事本。计算器。查看进程。查询ip,绘图工具,写字本,然后让命令行程序的标题改成了wuyuzhe,还改了颜色,然后最后运行了暂停。


非常好非常强大的东西,能够实现非常多的指令。

接下来。我们用可变參数列表,实现一个部分printf()函数的功能
print(“s ccc.\n”,”hello”,’b’,’i’,’t’);
print(char *format, …)

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
void print(char *format, ...)
{
    va_list arg;
    va_start(arg, format);

    while (*format)
    {
        switch (*format)
        {
            case 'c':
            {
                char tmp = va_arg(arg, char);
                putchar(tmp);
            }
                break;
            case 's':
            {
                        char *str = va_arg(arg, char*);
                        while (*str)
                        {
                            putchar(*str);
                            str++;
                        }
            }
                break;
            default:
                putchar(*format);
                break;
        }
        format++;
    }
    va_end(arg);
}
int main()
{
    print("s ccc.\n", "hello", 'b', 'i', 't');
    system("pause");
    return 0;
}
posted @ 2018-04-16 12:58  zhchoutai  阅读(147)  评论(0编辑  收藏  举报