c语言可变参数的问题

时间:2021-04-14 17:05:02
看到一个可变参数的函数如下:
/* Concatenate the NULL-terminated list of string arguments into
   freshly allocated space.  */
char *
concat_strings (const char *str0, ...)
{
  va_list args;
  int saved_lengths[5]; /* inspired by Apache's apr_pstrcat , (for efficiency matters?)*/
  char *ret, *p;

  const char *next_str;
  int total_length = 0;
  int argcount;

  /* Calculate the length of and allocate the resulting string. */

  argcount = 0;
  va_start (args, str0);
  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
  {
      int len = strlen (next_str);
      if (argcount < dim (saved_lengths))
saved_lengths[argcount++] = len;
      total_length += len;
  }
  va_end (args);
  p = ret = (char *)malloc (total_length + 1);

  /* Copy the strings into the allocated space. */
  argcount = 0;
  va_start (args, str0);
  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
  {
      int len;
      if (argcount < dim (saved_lengths))
len = saved_lengths[argcount++];
      else
len = strlen (next_str);
      memcpy (p, next_str, len);
      p += len;
  }
  va_end (args);
  *p = '\0';

  return ret;
}

我的疑问是:函数内没有任何语句跟可变参数...联系。va_xxxx系列的函数是怎么知道是对可变参数...进行操作的呢?

5 个解决方案

#1


知道最后一个固定参数就能知道可变参数开始的地址,关于到底压了多少参数,其实是不知道的,所以说很危险

#2


不是这样吧,带可变参数调用函数时,是把参数一个一个压入一个栈里,最后给你一个开头地址你可以根据此
地址一个一个取参数,具体怎么取,有你自己决定,参数什么意义,也有你自己决定.
//你看一下这个函数,不加参数运行一下就知道了.
int main(int argv,char **argc)
{
int i=0;
for(i=0;i<10;i++)
printf("%s\n",argc[i]);
}

#3


哦,是不是跟c语言内部实现的函数参数压栈有关?
以上一个函数为例,
调用concat_strings("we ", "are ", "the ", "champions", (char *)0);
程序会把参数按顺序排列,即每个字符串的地址按顺序排列,从而可变参数知道"we"的地址就可以按顺序找到下一个变量的地址.

是这样吗?

#4


谢谢cceczjxy() 

按照你说的,如下也可以。谢谢了
void
arg(int i, int j)
{
        int *ip = &i;
        printf("%d --- %d\n", *ip, *(ip + 1));
}

int
main()
{
        arg(4, 6);
}

#5


这是我写的错误处理函数,变长参数,其实就是K&R中的代码^_^
主意要include <stdarg.h>
     18 /***********our error handler***********/
     19 void printerr(char *fmt, ...)
     20 {
     21         va_list args;
     22
     23         va_start(args, fmt);
     24         fprintf(stderr, "error: ");
     25         vfprintf(stderr, fmt, args);
     26         fprintf(stderr, "\n");
     27         va_end(args);
     28         exit(1);
     29 }

我的疑问是:函数内没有任何语句跟可变参数...联系。va_xxxx系列的函数是怎么知道是对可变参数...进行操作的呢?

注意函数:va_start(),va_end(),还有va_list类型,这几个就是处理的关键

#1


知道最后一个固定参数就能知道可变参数开始的地址,关于到底压了多少参数,其实是不知道的,所以说很危险

#2


不是这样吧,带可变参数调用函数时,是把参数一个一个压入一个栈里,最后给你一个开头地址你可以根据此
地址一个一个取参数,具体怎么取,有你自己决定,参数什么意义,也有你自己决定.
//你看一下这个函数,不加参数运行一下就知道了.
int main(int argv,char **argc)
{
int i=0;
for(i=0;i<10;i++)
printf("%s\n",argc[i]);
}

#3


哦,是不是跟c语言内部实现的函数参数压栈有关?
以上一个函数为例,
调用concat_strings("we ", "are ", "the ", "champions", (char *)0);
程序会把参数按顺序排列,即每个字符串的地址按顺序排列,从而可变参数知道"we"的地址就可以按顺序找到下一个变量的地址.

是这样吗?

#4


谢谢cceczjxy() 

按照你说的,如下也可以。谢谢了
void
arg(int i, int j)
{
        int *ip = &i;
        printf("%d --- %d\n", *ip, *(ip + 1));
}

int
main()
{
        arg(4, 6);
}

#5


这是我写的错误处理函数,变长参数,其实就是K&R中的代码^_^
主意要include <stdarg.h>
     18 /***********our error handler***********/
     19 void printerr(char *fmt, ...)
     20 {
     21         va_list args;
     22
     23         va_start(args, fmt);
     24         fprintf(stderr, "error: ");
     25         vfprintf(stderr, fmt, args);
     26         fprintf(stderr, "\n");
     27         va_end(args);
     28         exit(1);
     29 }

我的疑问是:函数内没有任何语句跟可变参数...联系。va_xxxx系列的函数是怎么知道是对可变参数...进行操作的呢?

注意函数:va_start(),va_end(),还有va_list类型,这几个就是处理的关键