C语言中的可变参数函数(三个点)详解

本文介绍C语言中如何使用可变参数函数,包括va_start、va_arg和va_end等宏的运用,并提供ANSI标准与UNIX System V兼容形式的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. 使用宏实现可变参数

1.1 两种定义形式

1.2 宏功能简介

2. 示例代码

2.1 ANSI 标准形式示例

2.2 UNIX System V 兼容形式示例

在 C 语言编程中,常规函数的参数数量是固定的,调用时需要提供与形式参数一一对应的实参。然而,有时我们希望函数能够根据需求接受不同数量的参数,例如常见的 printf()scanf() 函数以及系统调用 execl() 等。那么,这类函数是如何实现的呢?

C 编译器通过一系列宏(如 va_startva_argva_end)来支持可变参数,这些宏有助于跨平台编程,增强代码的可移植性。

1. 使用宏实现可变参数

1.1 两种定义形式

ANSI 标准形式(推荐)

返回类型 函数名(固定参数列表, ...);

UNIX System V 兼容形式

返回类型 函数名(va_alist)
va_dcl

其中,va_dcl 是对 va_alist 的进一步声明,具体形式依赖于平台,但都以分号结束,因此在声明后不再添加分号。推荐使用符合 ANSI 标准的 <stdarg.h> 头文件,因为它具有更好的跨平台兼容性,而 <varargs.h> 主要用于保持与旧代码的兼容。

1.2 宏功能简介

  • va_start(argp, last_fixed_arg):初始化 argp,使其指向可变参数列表的起始位置。last_fixed_arg 是最后一个固定参数的名称。
  • va_arg(argp, type):返回参数列表中当前参数的值,并将 argp 移动到下一个参数位置。
  • va_end(argp):清理 argp,通常设置为 NULL

注意:调用者需要以特定方式指示可变参数的数量,例如以特定值(如空字符串 "" 或 -1)结束参数列表,或者像 printf() 那样通过第一个参数(格式化字符串)来确定参数个数。

2. 示例代码

2.1 ANSI 标准形式示例

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

// 函数原型声明,至少一个固定参数,后跟 ...
int demo(const char *msg, ...);

int main(void) {
    demo("DEMO", "This", "is", "a", "demo!", "");
    return 0;
}

int demo(const char *msg, ...) {
    va_list argp;
    int argno = 0;
    const char *para;

    va_start(argp, msg); // 初始化 argp
    printf("Message: %s\n", msg);
    while (1) {
        para = va_arg(argp, const char *); // 获取下一个参数
        if (para == NULL || para[0] == '\0') break; // 检查结束标志
        printf("Parameter #%d: %s\n", argno, para);
        argno++;
    }
    va_end(argp); // 清理
    return 0;
}

输出结果

Message: DEMO
Parameter #0: This
Parameter #1: is
Parameter #2: a
Parameter #3: demo!

2.2 UNIX System V 兼容形式示例

#include <stdio.h>
#include <varargs.h>

// 注意:此示例在不同平台上可能需要调整
int demo(va_alist)
va_dcl

int main(void) {
    demo("This", "is", "a", "demo!", "");
    return 0;
}

int demo(va_alist)
va_dcl {
    va_list argp;
    int argno = 0;
    char *para;

    va_start(argp);
    while (1) {
        para = va_arg(argp, char *);
        if (para == NULL || para[0] == '\0') break;
        printf("Parameter #%d: %s\n", argno, para);
        argno++;
    }
    va_end(argp);
    return 0;
}

输出结果

Parameter #0: This
Parameter #1: is
Parameter #2: a
Parameter #3: demo!

提示:在实际编程中,尽量使用 ANSI 标准形式的可变参数函数定义,并确保正确处理参数列表,以避免潜在的错误和未定义行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘色的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值