C语言之“可变参数与<stdarg.h>头文件”

简介: C语言之“可变参数与<stdarg.h>头文件”


<你想看的我这里都有😎 >

前言

       有时我们会希望函数带有可变数量的参数就像printf(cosnt char* format ...)和scanf(cosnt char* format ...)那样除了有一个参数 format 固定以外,后面的参数其个数和类型都是可变的,用三个点“…”作为参数占位符,而不是预定义(固定)数量的参数......

stdarg.h头文件

概念:我们可以利用C语言中<stdarg.h>头文件提供给我们的工具来编写带有变长参数列表的函数,stdarg.h头文件声明了一种va_list类型并定义了三个宏va_start(ap,v) 、va_arg(ap, type)、va_end(ap)

关于va_list类型的解释:一个用于存储可变参数信息的类型。在使用可变参数之前,需要先声明一个 va_list 类型变量来保存参数列表

关于va_start(ap,v) 宏的解释:该宏用于初始化 va_list类型的变量,并将其与第一个有准确命名的参数关联起来(通过地址实现,类似于数组的形式),这样可以在后续代码中逐个访问每个可变参数

关于va_arg(ap, type) 宏的解释:该宏用于从已初始化的 va_list 类型的变量中获取下一个可变参数,并指定其期望的类型。通过多次调用此宏可以逐步遍历所有传递给函数或宏作为额外实际参数(而不是具名形式) 的所有额外实际值

关于va_end(ap) 宏的解释:该宏负责清理并释放由 va_start()宏初始化的资源。通常,在使用完所有可变数量的实参之后应调用此宏以确保正确结束处理过程

关于宏的具体定义如下,但为了方便理解不做过多解释,只需要知道大概的使用方式即可:

typedef char * va_list;
// 把 n 圆整到 sizeof(int) 的倍数
#define _INTSIZEOF(n)       ( (sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1) )
// 初始化 ap 指针,使其指向第一个可变参数。v 是变参列表的前一个参数
#define va_start(ap,v)      ( ap = (va_list)&v + _INTSIZEOF(v) )
// 该宏返回当前变参值,并使 ap 指向列表中的下个变参
#define va_arg(ap, type)    ( *(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type)) )
// /将指针 ap 置为无效,结束变参的获取
#define va_end(ap)             ( ap = (va_list)0 )typedef char * va_list;

注意事项:

1、C99中增加了一个宏va_copy

2、ap 是一个 va_list 类型的变量

3、type 是参数的类型

具体使用步骤:

  • 定义一个函数,第一个参数是指定类型,后续参数用省略号代替
  • 在函数定义中创建一个 va_list 类型变量
  • 使用第一个参数和 va_start() 宏初始化 va_list类型的变量为一个参数列表
  • 使用 va_arg() 宏和 va_list 变量来访问参数列表中的每个项
  • 使用宏 va_end() 来清理赋予 va_list 类型变量的内存

实例:遍历并求和所有传递给sum函数的额外实际参数

#include <stdio.h>
#include <stdarg.h>
int sum(int count, ...) {
    int total = 0;
    va_list args;
    va_start(args, count);
    for (int i = 0; i < count; i++) {
        int num = va_arg(args, int);
        total += num;
    }
    va_end(args);
    return total;
}
int main() {
    int result = sum(4, 10, 20, 30, 40);
    printf("Sum: %d\n", result);
    return 0;
}

~over~

相关文章
|
23天前
|
C语言
【C语言】头文件命名详解 - 《铁头无敌 ! 》
头文件在C语言编程中起着组织代码和提高代码复用性的作用。标准头文件提供了丰富的库函数,而自定义头文件可以将常用函数、宏定义、类型定义等封装起来,以便在多个源文件中共享。遵循良好的头文件命名和使用约定,有助于编写清晰、易维护的C语言程序。
66 3
|
7月前
|
存储 编译器 C语言
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题(下)
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题
114 5
|
4月前
|
C语言
【C语言小知识】备选拼写:iso646.h头文件
【C语言小知识】备选拼写:iso646.h头文件
|
7月前
|
算法 编译器 C语言
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题(中)
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题
68 2
|
7月前
|
算法 编译器 C语言
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题(上)
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题
53 1
|
7月前
|
编译器 C语言
【C语言】—— 可变参数列表
【C语言】—— 可变参数列表
【C语言】—— 可变参数列表
|
7月前
|
编译器 API C语言
C语言头文件
C语言头文件
117 0
|
7月前
|
存储 编译器 Serverless
C语言可变参数
C语言可变参数
60 0
|
7月前
|
Serverless C语言
【C语言】va_list(可变参数处理)
【C语言】va_list(可变参数处理)
137 0
|
7月前
|
编译器 C语言
C语言基础专题 - 头文件引用
C语言基础专题 - 头文件引用
158 0