zoukankan      html  css  js  c++  java
  • C语言可选性自变量(摘自C语言核心技术)

    C语言允许定义自变量数量可变的函数,这称为variadic函数。这样的函数需要固定数目的强制性自变量(mandatory argument),后面是数量可变的可选性自变量。这样的函数必须有“至少一个”强制性自变量。可选性自变量的类型可能会改变,可选性自变量的数量可能由“强制性自变量的值”所决定,或者由“用来定义可选性自变量列表的特殊值”所决定。

    C语言中,最有名的variadi函数范例是printf()和scanf()。这两个函数都有一个强制性自变量,也就是格式字符串;格式化字符串中的转换修饰符决定可选性自变量的类型和数量。

    对于每一个强制的变量来说,函数头会显示一个适当的参数,像一般的函数声明一样。参数列表的规格是强制性参数在前(用逗号隔开),后面跟着一个逗号和省略符号(...),这个省略符号就代表可选性自变量。

    variadic函数要存取可选性自变量时,必须通过一个类型为va_list的对象,它包含了自变量信息。这种类型的对象也称为“自变量指针”(argument pointer),它最少包含此堆栈中一个自变量的位置。可以使用这个自变量指针前移到下一个可选性自变量,这样的话,函数就可以存取所有的可选性自变量。va_list类型被定义在stdarg.h头文件中。

    当编写支持“数量可变自变量”的函数时,必须用va_list类型定义自变量指针,以存取可选性自变量。在下面的讨论中,va_list对象被命名为argptr。可以用四个宏来处理此自变量指针,这些宏都定义在stdarg.h头文件中:

    void va_start(va_list argptr, lastparam);

    va_start宏使用第一个可选性自变量的位置来初始化argptr自变量指针。此宏的第二个自变量必须是“此函数最后一个有名称的参数”的名称。开始使用可选性自变量之前,你必须先调用此宏。

    type va_arg(va_list argptr, type);

    va_arg宏会取得目前argptr所引用的可选性自变量,也会将argptr前移到下一个自变量。va_arg宏的第二个自变量是“刚刚读入”自变量的类型。

    void va_end(va_list argptr);

    当不再需要自变量指针时,你必须调用va_end宏。若干想使用va_start或va_copy来重新初始化一个之前用过的自变量指针,也必须先调用va_end。

    void va_copy(valist dest, va_list src);

    va_copy宏使用目前的src来初始化自变量指针dest。然后就可以使用dest来存取可选性自变量列表,从src引用的位置开始。

    1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <stdarg.h>
    4
    5  void myprintf(const char *fmt, ...)
    6 {
    7 /*
    8 * va_list 类型用于声明一个变量, 该变量将依次引用各参数.
    9 * va_start 将变量初始化为指向第一个无名参数的指针.
    10 * va_arg 该函数都将返回一个参数, 并将变量指向下一个参数.
    11 */
    12 va_list ap;
    13 va_start(ap, fmt);
    14 const char *p;
    15 for ( p = fmt; *p; p++) {
    16 if (*p == '%') {
    17 switch(*++p) {
    18 case 'd':
    19 printf("%d", va_arg(ap, int));
    20 break;
    21 case 'f':
    22 printf("%f", va_arg(ap, double));
    23 break;
    24 case 's':
    25 printf("%s", va_arg(ap, char *));
    26 break;
    27 default:
    28 break;
    29 }
    30 } else {
    31 putchar(*p);
    32 }
    33 }
    34 va_end(ap);
    35 }
    36  int main(int argc, char *argv[])
    37 {
    38 myprintf("%s = %d / %f\ = %f\n", "100 / pi", 100, 3.1415926, 100 / 3.1415926);
    39 getch();
    40 return 0;
    41 }

    执行结果为,在控制台输出:

    100 / pi = 100 / 3.141593 = 31.830989

  • 相关阅读:
    js对象与字符串相互转换
    11 ~ express ~ 解决 cookie 中文报错的问题
    10 ~ express ~ 使用 cookie 保存用户 信息
    href="javacript:;" href="javacript:void(0);" href="#"区别。。。
    9 ~ express ~ 用户注册
    8 ~ express ~ 基于数据库的验证
    SpringBoot整合RocketMQ
    RabbitMQ(五)消息发送失败后的处理
    分享一些JVM常见的面试题(转)
    双亲委派模型
  • 原文地址:https://www.cnblogs.com/arci/p/1972208.html
Copyright © 2011-2022 走看看