zoukankan      html  css  js  c++  java
  • C语言不定参数

    最近,遇到一个c语言的不定参数问题。其实,对于c语言的不定参数问题,只需要三个函数就可以搞定了。这三个函数的头文件是<stdarg.h>,其实下面的三个函数都是一个宏定义(macro)。
        这三个函数是:
        void va_start(va_list ap, last);
        type va_arg(va_list ap, type);
        void va_end(va_list ap);
        如果需要进行其他的一些操作,可以查看一下man手册进行查询。
        在这三个函数解释之前,先看一个变量va_list,这个变量的类型是什么呢?通过查看内核源代码,一直追踪下去,才发现它的类型是void *类型的。
        对于va_start(va_list ap, last)函数,这个函数是用来初始化指针变量ap(va_list类型)的,以后处理参数就是默认从ap处开始处理。last一般为char *传过来参数列表的第一个参数。
        对于va_arg(va_list ap, type)函数来说,就是将ap指针按照type类型向后移动,然后取出ap指针所指的那个参数。
        对于va_end(va_list ap)一般和va_start(va_list ap, last)配套使用,做一些善后处理的事情。
        这里有一个问题,当我们取参数的时候,如何判断我们要取的参数已经取完了?开始我是这么想的,通过va_arg的返回值进行判断,通过查阅资料,都是这么说的,看来我的猜想是对的。当我把程序写出来进行测试的时候,发现不是这样的:
    #include <stdio.h>
    #include <stdarg.h>
    int sum(const int , ...);
    int main(void)
    {
        printf("The result is:%d/n", sum(10, 9, 8));
        return 0;
    }
    int sum(const int first, ...)
    {
        va_list argp;
        int sum = 0;
        int tmp;
        va_start(argp, first);
        sum += first;
        printf("%d/n", first);
        while((tmp = va_arg(argp, int)) != 0) {
            printf("%d/n", tmp);
            sum += tmp;
        }
        va_end(argp);
        return sum;
    }
    这个程序的运行结果是:
    10
    9
    8
    6676468
    134513824
    The result is:141190319
        这个结果说明,通过va_arg的返回值进行参数是否取完来判断是有问题的。
        会不会是通过argp的值来判断的呢?让我们来做个测试:
    #include <stdio.h>
    #include <stdarg.h>
    int sum(const int , ...);
    int main(void)
    {
        printf("The result is:%d/n", sum(10, 9, 8));
        return 0;
    }
    int sum(const int first, ...)
    {
        va_list argp;
        int sum = 0;
        int tmp;
        va_start(argp, first);
        sum += first;
        printf("%d/n", first);
        while(argp) {
            tmp = va_arg(argp, int);
            printf("%d/n", tmp);
            sum += tmp;
        }
        va_end(argp);
        return sum;
    }
        这个程序的执行结果出乎我的意料,出现了段错误。
        至于如何修改这个程序把不定参数取出来,我还是没有找到解决方法。后来,我想到了printf()函数,我查看了它的源代码,其中主要是调用了vsprintf()函数,至于为什么调用vsprintf()函数,我想可能是为了实现类似于fprintf()之类的函数调用的方便,这样也提高了函数的利用率。printf()函数的主要代码:
    328 va_start(args, fmt);
    329 n = vsprintf(sprint_buf, fmt, args);
    330 va_end(args);
        我继续查看了vsprintf()函数,结果发现,在这个函数当中,它好像是通过判断字符串当中“%”号的多少来决定后面参数的个数的。想到这里,我断定,在想调用不定参数这样的函数的时候,其实是需要指出参数的个数的,只是是通过间接的方式。比如我们最熟悉的printf()函数,其实我们在第一个参数当中,通过%号已经指出了参数的个数,不是吗?
        想到这里,我想到了之前看到man手册中给出的例子为什么是这样的:
    #include <stdio.h>
           #include <stdarg.h>
           void
           foo(char *fmt, ...)
           {
               va_list ap;
               int d;
               char c, *s;
               va_start(ap, fmt);
               while (*fmt)
                   switch (*fmt++) {
                   case 's': /* string */
                       s = va_arg(ap, char *);
                       printf("string %s/n", s);
                       break;
                   case 'd': /* int */
                       d = va_arg(ap, int);
                       printf("int %d/n", d);
                       break;
                   case 'c': /* char */
                       /* need a cast here since va_arg only
                          takes fully promoted types */
                       c = (char) va_arg(ap, int);
                       printf("char %c/n", c);
                       break;
                   }
               va_end(ap);
           }
        这里的话,不是就通过第一个参数指定之后才读取的吗?其实我觉得是间接的告诉了参数的个数。
        通过上面的分析,下面做了一个简单的不定参数的应用。
        问题描述:给定一些字符串,求出它们的最长开始字串。
        实验代码如下:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdarg.h>
    void fun(char *fmt, ...);
    int main()
    {
        fun("sss", "fanabcd", "fanfanfanfan", "fanyyyyyyyyyyyy");//sss 表示了不定参数的个数
        return 0;    
    }
    void fun(char *fmt, ...)
    {
        va_list argp;
        char * str, res[20] = {0};
        int i;
        va_start(argp, fmt);
        if(*fmt == 's') {
            str = va_arg(argp, char *);
            strcpy(res, str);
        }
        fmt++;
        while(*fmt) {
            if(*fmt++ == 's') {
                str = va_arg(argp, char *);
                i = 0;
                while(res[i] != '/0') {
                    if(res[i] != str[i]) {
                        res[i] = 0;
                        break;
                    }
                    i++;
                }
            }
        }
        va_end(argp);
        printf("The result is:%s/n", res);
    }
        程序的执行结果是:
    The result is:fan
        通过这样的折腾,就把c语言的不定参数简单地应用起来了

  • 相关阅读:
    2021/3/16
    2021/3/15
    plist
    百度小程序更新管理
    uni-app v-for v-modal
    小程序中不能使用字符串模板吗
    条件编译
    百度app 和小程序版本关系
    uni-app 全局变量的几种实现方式
    canvas 换行处理
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/6401841.html
Copyright © 2011-2022 走看看