以下是通义千问生成的内容:

va_list 是 C 语言中用于处理可变参数函数(variadic functions)的一个 类型,你可以把它理解为一个“指向可变参数列表的指针”或“遍历参数的游标”。

它和 va_startva_argva_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 = 3
    • va_start(ap, n)ap 指向 10
    • 第一次 va_arg(ap, int) → 取出 10ap 移动到 20
    • 第二次 → 取出 20ap 移动到 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 指向 42
  • vsprintf 内部:
    • 遇到 %d → 调用 va_arg(ap, int) → 取出 42
    • 遇到 %s → 调用 va_arg(ap, char*) → 取出 "Alice"
  • 最终生成字符串 "Value: 42, Name: Alice"

⚠️ 使用 va_list 的注意事项

  1. 必须包含头文件#include <stdarg.h>
  2. 必须调用 va_end:否则可能导致未定义行为。
  3. 类型必须匹配va_arg(ap, int) 必须对应一个 int 类型的参数,否则结果未定义。
  4. 没有类型检查:C 语言不会检查你传的参数类型是否匹配格式符,容易出错(如 printf("%d", "hello") 会崩溃)。
  5. 至少一个固定参数:可变参数函数必须至少有一个固定参数,va_start 需要它来定位。

✅ 总结

  • va_list 就像一个“参数游标”,让你可以遍历 ... 中的参数。
  • 它是实现 printfscanfu1_printf 等函数的基础。
  • 使用流程固定:va_listva_startva_arg(多次)→ va_end

掌握它,你就能写出更灵活的 C 函数!

posted on 2025-10-24 13:48  快乐的乙炔  阅读(0)  评论(0)    收藏  举报  来源