建站网站排行榜,哪里有建设网站中的视频下载,做简单网站的框架,可以在线制作简历的网站简介#xff1a; CSDN博客专家#xff0c;专注Android/Linux系统#xff0c;分享多mic语音方案、音视频、编解码等技术#xff0c;与大家一起成长#xff01; 优质专栏#xff1a;Audio工程师进阶系列【原创干货持续更新中……】#x1f680; 人生格言#xff1a; 人生… 简介 CSDN博客专家专注Android/Linux系统分享多mic语音方案、音视频、编解码等技术与大家一起成长 优质专栏Audio工程师进阶系列【原创干货持续更新中……】 人生格言 人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注Android系统攻城狮 1.前言 本篇目的C之va_start、vasprintf、va_end应用总结。 在C/C语言中va_start、vasprintf和va_end是与可变参数相关的函数。它们通常与stdarg.h头文件一起使用。 va_start函数 va_start函数用于初始化可变参数列表。它接受两个参数第一个参数是一个va_list类型的变量第二个参数是最后一个固定参数的前一个参数的名称。这个函数将va_list类型变量初始化为指向可变参数列表的起始位置。 vasprintf函数 vasprintf函数用于将格式化的可变参数输出到动态分配的字符串中。它接受两个参数第一个参数是一个指向char指针的指针第二个参数是一个格式化字符串。这个函数会根据格式化字符串和可变参数列表生成一个动态分配的字符串并将指针保存在第一个参数所指向的位置。 va_end函数 va_end函数用于结束可变参数的获取。它接受一个参数即一个va_list类型的变量。这个函数对可变参数列表进行清理使其无法再被访问。
通常在需要处理可变参数的情况下使用实现Printf风格的函数或者处理命令行参数时。
2.应用实例
1.v1.0
#include stdio.h
#include stdarg.hvoid sum(int count, ...)
{va_list args;int total 0;// 初始化可变参数列表va_start(args, count);// 遍历可变参数列表并求和for (int i 0; i count; i){int num va_arg(args, int);total num;}// 结束可变参数列表va_end(args);printf(Sum: %d\n, total);
}int main()
{sum(3, 1, 2, 3); // 输出 Sum: 6return 0;
}va_start是一个宏用于处理可变参数列表。它的原理是基于C语言的可变参数机制。
va_start宏的工作原理如下 首先通过传入的参数列表的类型信息和格式化字符串来确定参数列表的起始位置。 然后通过指针运算和类型大小来计算出参数列表中各个参数的位置。 最后将参数列表位置信息保存在一个va_list类型的变量中供后续函数进行处理。
va_start宏的实现通常依赖于编译器和操作系统的底层支持。它使用了一些机制来获取参数列表的信息如栈帧结构、类型信息、指针运算等。
具体实现的细节可能因编译器和操作系统而异但通常会涉及以下步骤 获取栈帧指针va_start宏需要通过访问栈来获取参数列表的位置信息。它首先获取当前函数的栈帧指针可以通过编译器提供的相关函数或底层汇编指令来实现。 计算参数列表位置通过栈帧指针和参数类型大小va_start宏可以计算出参数列表中各个参数的位置。这通常涉及指针运算根据参数类型大小来移动指针位置。 保存参数列表信息va_start宏将参数列表位置信息保存在一个va_list类型的变量中以便后续的函数进行处理。可以将栈帧指针和计算得到的参数列表位置信息存储在va_list变量中。
va_start宏使用一些编译器和操作系统提供的底层机制来实现可变参数的处理。具体实现可能会因编译器和操作系统的不同而异也可能受到编译器的优化策略的影响。
2.v2.0
#include stdio.h
#include stdarg.hchar* format_string(const char* format, ...)
{va_list args;char* str;// 初始化可变参数列表va_start(args, format);// 格式化字符串并存储到动态分配的字符串中int length vasprintf(str, format, args);// 结束可变参数列表va_end(args);printf(Formatted String: %s\n, str);printf(String Length: %d\n, length);return str;
}int main()
{char* result format_string(Hello %s, your age is %d., John, 25);// 输出 Formatted String: Hello John, your age is 25.// 输出 String Length: 30free(result); // 释放动态分配的字符串return 0;
}va_end是一个宏用于结束对可变参数列表的访问。它的原理是基于C语言的可变参数机制。
va_end宏的工作原理如下 首先它接收一个va_list类型的变量作为参数该变量保存了参数列表的位置信息。 接着通过一系列机制如编译器和操作系统的底层支持实现将参数列表进行清理和释放的操作。 最后将va_list类型的变量标记为无效以确保之后对它的访问是无效的。
具体实现的细节可能因编译器和操作系统而异但通常会涉及以下步骤 清理参数列表va_end宏根据参数列表的位置信息使用特定的机制将参数列表进行清理。它可能涉及释放资源、清理栈上的参数值等操作。具体的清理操作由编译器和操作系统提供的底层支持来实现。 使va_list变量失效为了确保在之后对va_list变量的访问是无效的va_end宏将该变量标记为无效。这样可以避免误用已经结束的参数列表。
va_end宏的实现依赖于编译器和操作系统的底层支持。具体实现的细节可能会因编译器和操作系统的不同而异。但无论实现细节如何va_end宏的目标都是确保正确清理和释放可变参数列表所占用的资源并将va_list变量标记为无效。
3.v3.0
#include iostream
#include cstdarg
#include cstdio
#include cstdlib
#include stringusing namespace std;string AStringPrintf(const char *format, ...) {va_list ap;va_start(ap, format);char *buffer;int bufferSize vasprintf(buffer, format, ap);va_end(ap);if(bufferSize 0) {return string();}string result(buffer);free(buffer);buffer NULL;return result;
}int main(){char str[64]{1,2,3,5,6,7,8,9};string buf AStringPrintf(str);printf(buf %s\n,buf.c_str());
} vsnprintf函数接收一个格式化字符串和一个va_list类型的参数列表。利用格式化字符串它将参数列表中的数据转换为相应的字符串格式。 首先vsnprintf函数根据格式化字符串中的格式指示符逐个读取参数列表的值并根据指示符的要求对其进行格式化。 然后vsnprintf函数根据格式化的结果将其写入到指定的缓冲区中。它会确保写入的数据不超过指定的缓冲区大小。 最后vsnprintf函数会在写入完成后返回实际写入的字符数不包括结尾的’\0’。如果缓冲区大小不足以容纳格式化后的字符串vsnprintf函数会截断字符串但仍然会返回实际要写入的字符数。
需要注意的是由于vsnprintf函数是经过格式化而得到的字符串的长度是不确定的因此在使用之前需要分配足够的缓冲区来存储格式化后的字符串以避免缓冲区溢出的情况发生。
vsnprintf函数是一个用于以固定格式将可变参数格式化为字符串的函数。它将格式化的结果写入指定的缓冲区并返回实际写入的字符数。这个函数在C中可用于处理可变参数并将其转换为字符串格式。
4.v4.0
#include stdio.h
#include stdarg.h
#include stdlib.hvoid dynamic_print(const char* format, ...)
{va_list args;va_start(args, format);char* dyn_str NULL;size_t str_length 0;// 计算动态生成字符串所需的长度str_length vsnprintf(NULL, 0, format, args);// 为字符串动态分配内存dyn_str (char*)malloc(str_length 1);// 动态生成字符串vsnprintf(dyn_str, str_length 1, format, args);printf(%s, dyn_str);free(dyn_str);va_end(args);
}int main(){int num1 10;int num2 20;dynamic_print(Sum: %d %d %d\n, num1, num2, num1 num2);return 0;
}