以下是通义千问生成的内容:
va_list 是 C 语言中用于处理可变参数函数(variadic functions)的一个 类型,你可以把它理解为一个“指向可变参数列表的指针”或“遍历参数的游标”。
它和 va_start、va_arg、va_end 一起使用,让你可以编写像 printf 一样支持 ... 参数的函数。
🧩 va_list 相关宏和函数
| 名称 | 作用 |
|---|---|
va_list ap; | 定义一个 va_list 类型的变量,用于遍历参数。 |
va_start(ap, last_fixed_param); | 初始化 ap,使其指向第一个可变参数。last_fixed_param 是函数最后一个固定参数。 |
va_arg(ap, type); | 从参数列表中取出下一个参数,类型为 type,并让 ap 指向下一个。 |
va_end(ap); | 清理 va_list,通常在函数结束前调用。 |
✅ 举个实际例子:自己实现一个 sum 函数
假设你想写一个函数,计算任意多个整数的和:
#include <stdio.h>
#include <stdarg.h> // 必须包含这个头文件
// 函数声明:第一个参数 n 表示后面有多少个数要相加
int sum(int n, ...)
{
va_list ap; // 1. 定义 va_list 变量
int total = 0;
va_start(ap, n); // 2. 初始化 ap,n 是最后一个固定参数
for (int i = 0; i < n; i++)
{
int value = va_arg(ap, int); // 3. 取出下一个 int 类型的参数
total += value;
}
va_end(ap); // 4. 结束使用 va_list
return total;
}
// 使用示例
int main()
{
int result1 = sum(3, 10, 20, 30); // 60
int result2 = sum(5, 1, 2, 3, 4, 5); // 15
printf("Result1: %d\n", result1);
printf("Result2: %d\n", result2);
return 0;
}
🔍 执行过程:
sum(3, 10, 20, 30)n = 3va_start(ap, n)→ap指向10- 第一次
va_arg(ap, int)→ 取出10,ap移动到20 - 第二次 → 取出
20,ap移动到30 - 第三次 → 取出
30 - 循环结束,返回
60
🔁 回到你的 u1_printf 函数
void u1_printf(char* fmt, ...) {
uint16_t len;
va_list ap; // 定义 ap
va_start(ap, fmt); // 初始化 ap,fmt 是最后一个固定参数
uint8_t buf[200];
vsprintf((char*)buf, fmt, ap); // vsprintf 内部会用 va_arg 从 ap 中取参数
va_end(ap);
len = strlen((char*)buf);
HAL_UART_Transmit(&huart1, buf, len, 100); // 建议加超时
}
当你调用:
u1_printf("Value: %d, Name: %s", 42, "Alice");
fmt = "Value: %d, Name: %s"va_start(ap, fmt)→ap指向42vsprintf内部:- 遇到
%d→ 调用va_arg(ap, int)→ 取出42 - 遇到
%s→ 调用va_arg(ap, char*)→ 取出"Alice"
- 遇到
- 最终生成字符串
"Value: 42, Name: Alice"
⚠️ 使用 va_list 的注意事项
- 必须包含头文件:
#include <stdarg.h> - 必须调用
va_end:否则可能导致未定义行为。 - 类型必须匹配:
va_arg(ap, int)必须对应一个int类型的参数,否则结果未定义。 - 没有类型检查:C 语言不会检查你传的参数类型是否匹配格式符,容易出错(如
printf("%d", "hello")会崩溃)。 - 至少一个固定参数:可变参数函数必须至少有一个固定参数,
va_start需要它来定位。
✅ 总结
va_list就像一个“参数游标”,让你可以遍历...中的参数。- 它是实现
printf、scanf、u1_printf等函数的基础。 - 使用流程固定:
va_list→va_start→va_arg(多次)→va_end。
掌握它,你就能写出更灵活的 C 函数!
浙公网安备 33010602011771号