C语言回顾(可变参数篇)

可变参数

C 语言允许定义参数数量可变的函数,这称为可变参数函数。这种函数需要固定数量的强制参数,后面是数量可变的可选参数。

常见的可变参数函数
int printf(const char* format,…)
int scanf(const char *format,…)
固定参数 format ,可选参数用“...”最为参数占用符

任何一个可变参数的函数都可以分为两部分:固定参数和可选参数。至少要有一个固定参数,其声明与普通函数参数声明相同;可选参数由于数目不定(0个或以上),声明时用"…"表示。固定参数和可选参数共同构成可变参数函数的参数列表。

可变参数获取对象
// 函数add() 计算可选参数之和
// 参数:第一个强制参数指定了可选参数的数量,可选参数为double类型
// 返回值:和值,double类型
double add( int n, ... )
{
  int i = 0;
  double sum = 0.0;
  va_list argptr;
  va_start( argptr, n );   // 初始化argptr
  for ( i = 0; i < n; ++i )  // 对每个可选参数,读取类型为double的参数,
    sum += va_arg( argptr, double ); // 然后累加到sum中
  va_end( argptr );
  return sum;
}

在上面的例子中,用到了va_list ,va_start,va_arg,va_end 包含头文件<stdarg.h>

va_list :其实就是通过typedef 定义的一个指针类型,它用来定义一个指针。

va_start:其实就是为了获取可选参数的地址,然后保存在第一个参数中。它有两个参数,一个参数是va_list 类型的,用来存放第一个可选参数的地址。另一个参数是与可选参数相邻的那个强制参数。其实在程序的栈中,函数的所有参数都是在内存中连续分布的,所以可以通过强制参数的地址来获取可选参数的地址,然后保存在第一个参数中

va_arg:这个宏取得 type 类型的可变参数值。该函数有两个参数,第一个参数是当前可变参数的地址,第二个参数是当前可变参数的类型。通过地址和类型来确定可变参数的值,然后返回。这个函数调用过后,第一个参数的值会变化,它会指向参数列表中下一个参数。

va_end:必须和va_start 配合使用,使用 va_start 宏的函数中退出之前,必须调用一次 va_end 宏。相当于释放了内存。

__VA_ARGS__

个可变参数的宏,它使得可以在宏定义中使用可变参数列表,可变参数的个数最少为1,否则编译会出错。

//用法如下,在宏定义中替代 ... :
#define my_print2(fmt,...)  printf(fmt,__VA_ARGS__)

此外还有一个 ##__VA_ARGS__ ,它可以允许可变参数的个数为0个。

#define my_print2(fmt,...)  printf(fmt,__VA_ARGS__)
my_print2("i=%d,j=%d\n",i,j) //正确打印
my_print2("iiiiiii\n") //编译失败 只有一个参数,可变参数的个数为0
//改为:
#define my_print2(fmt,...)  printf(fmt,##__VA_ARGS__)
my_print2("iiiiiii\n")
vsprintf与vsnprintf

vsprintf与vsnprintf的用法差不多,区别在于vsnprintf限制了最大的转换长度,可以防止越界。一般选用vsnprintf。

int vsprintf (char * s, const char * format, va_list arg );
将可变参数列表的格式化数据写入字符数组s中
s:这是指向一个字符数组的指针,该数组存储了字符串
format:要格式化输出的字符串
arg:可变参数列表
返回值:如果成功,则返回写入的字符总数,否则返回一个负数
用法:
int vspfunc(char *format, ...)
{
   va_list aptr;
   int ret;

   va_start(aptr, format);
   ret = vsprintf(buffer, format, aptr);
   va_end(aptr);  
   return(ret);
}
int main()
{
   int i = 5;
   float f = 27.0;
   char str[50] = "runoob.com";
   vspfunc("%d %f %s", i, f, str);
   printf("%s\n", buffer);  
   return(0);
}

int vsnprintf(char *s, size_t n, const char *format, va_list arg)
s:这是指向一个字符数组的指针,该数组用来存储字符串
n:在缓冲区中使用的最大字节数。生成的字符串的长度至多为n-1,为额外的终止空字符留下空间
format:要格式化输出的字符串
arg:可变参数列表
返回值:如果成功,则返回写入的字符总数,不包括终止空字符,否则返回一个负数
用法:
void test(const char * format, ...)
{
     char buf[4069];

     va_list list;

 
     va_start(list, format);
 
     vsnprintf(buf, 4069, format, list);
 
     va_end(list);
 
     printf("%s\n", buf);
 } 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值