C++漫游记 (3):C++可变参数的格式化

在 C/C++ 中,可变参数列表以省略号运算符 ...表示。它具有许多用途,具体取决于具体的使用场景。 最初在 C 中用作可变函数参数列表的抽象声明符;在 C++ 中,可用于异常处理 catch 块中;而在 C++11 中,则用于可变参数模板。

printf("Hello, World! \n");

说起可变参数,printf() 可以说是最经典的应用之一。

int printf(
	const char *format [,
	argument]...
); 

从接触 C/C++ 开始,‘printf()’ 们可谓如影随形。在实际的应用中,界面数据的格式化输出、日志的格式化输出,这些都和可变参数密不可分。

可变参数列表的格式化,主要有两种方式:
1. 可变参数列表va_list和vsprintf
2. 可变参数模板和sprintf (C++11)

接下来,以 format_string() 函数为例进行说明。以下是主体部分:

#include 
#include 
#include 

void format_string(const char* format, ...)
{
   
    // TODO:...
}

int main()
{
   
    format_string("%s, %s", "hello", "this is a string.");
    return 0;
}

1. 可变参数列表va_list和vsprintf

1.1 va_start、va_end、vsprintf 的使用

#define MAX_BUFFER 128

void format_string(const char* format, ...)
{
   
    char buffer[MAX_BUFFER] = {
    0 };

    va_list args;
    va_start(args, format);
    vsprintf(buffer, format, args); // warning C4996: 'vsprintf': This function or variable may be unsafe. Consider using vsprintf_s instead.
    va_end(args);

    puts(buffer);
}
输出:hello, this is a string.(加上结束符’\0’,共25个字符)

以上便是基于 va_list 的可变参数格式化实现。args 是指向参数列表的指针,通过 va_start 将 args 设置为传递给函数的参数列表中的第一个可选参数,然后使用 vsprintf 进行参数检索和格式化输出。
有没有很眼熟?vsprintf 比我们常用的 sprintf 前面多一个v,表示是用于可变参数列表(variable-argument list) 的。它们的区别在于,sprintf 的入参是可变参数列表(省略号),而 vsprintf 的入参是可变参数列表指针。

1.2 “warning C4996”的前因后果

在编译过程中,会有这样一个警告:warning C4996: 'vsprintf': This function or variable may be unsafe. Consider using vsprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 也可能是 error C4996, 这取决于VS项目属性配置中 “C/C++” 下是否开启了SDL检查。

通常情况下,我们会选择忽略或屏蔽这个警告。一般情况下是可以这样操作,但是会存在潜在问题,后面会进行说明。出现C4996的提示,是由于微软为了增强安全机制,弃用了部分C运行时库(CRT)函数,以_s结尾的同名函数替代。微软认为,这些函数是安全错误的常见来源,因为它们不会阻止覆盖内存的操作。这个怎么理解呢?接下来看看错误是如何出现的。

首先,将输出缓冲区 MAX_BUFFER 大小调整为 20,看看会发生什么。

#define MAX_BUFFER 20

void format_string(const char* format, ...)
{
   
    

你可能感兴趣的:(C++漫游记,c++,字符串,c++11)