C++变量参数错误
C++ variable argument error
我最近在 MSVC (2013) 中偶然发现了一个奇怪的行为,我想澄清一下有关变量参数的问题。
似乎在“...)”之前有多个参数会导致意外行为
int formatString(const char* msg, char* buffer, int bufferLength, ...)
{
int length = 0;
if (msg != nullptr) {
va_list args;
va_start(args, msg);
length = vsnprintf_s(buffer, bufferLength, bufferLength, msg, args);
va_end(args);
}
return length;
}
像这样调用这个函数
const char* message = "A word: %s and a number %d";
const int bufferLength = 1024;
char buffer[bufferLength];
int formattedMsgLen = formatString(message, buffer, bufferLength, "cheese", 4);
会立即导致程序崩溃。如果我在
之前将缓冲区 memset 为 0
memset(buffer, 0, 1024); // We know sizeof(char) == 1
这被写入缓冲区:
"A word: A word: and a number 1024".
这是完全错误的...
但是,如果我将函数更改为采用结合了前三个参数的结构
struct Message
{
const char* msg;
char* buffer;
int bufferLength;
};
int formatString(Message msg, ...)
{
int length = 0;
if (msg.msg != nullptr) {
va_list args;
va_start(args, msg);
length = vsnprintf_s(msg.buffer, msg.bufferLength, msg.bufferLength, msg.msg, args);
va_end(args);
}
return length;
}
像这样调用新函数时:
const int bufferLength = 1024;
char buffer[bufferLength];
Message msg;
msg.buffer = buffer;
msg.msg = "A word: %s and a number %d";
msg.bufferLength = bufferLength;
int formattedMsgLen = formatString(msg, "cheese", 4);
写入缓冲区:
"A word: cheese and a number 4"
哪个是正确的,这就是我所期望的。我认为您之前只能将 vaargs 与只有一个参数的函数一起使用吗?我认为情况并非如此,因为下面的函数有多个第一个参数
int fprintf(FILE *, const char *fmt, ...);
int sprintf(char *s, const char *fmt, ...);
这可能是编译器中的错误吗?然而不太可能....
可能不是,我做了一些愚蠢的事情,但我肯定对正在发生的事情感到困惑。如果有人能对此有所了解,我将不胜感激。
谢谢!
va_start()
必须在可变参数列表之前使用 last 参数的名称调用:
int formatString(const char* msg, char* buffer, int bufferLength, ...)
{
// ...
va_list args;
// va_start(args, msg); <-- WRONG!
va_start(args, bufferLength);
// ...
}
我最近在 MSVC (2013) 中偶然发现了一个奇怪的行为,我想澄清一下有关变量参数的问题。
似乎在“...)”之前有多个参数会导致意外行为
int formatString(const char* msg, char* buffer, int bufferLength, ...)
{
int length = 0;
if (msg != nullptr) {
va_list args;
va_start(args, msg);
length = vsnprintf_s(buffer, bufferLength, bufferLength, msg, args);
va_end(args);
}
return length;
}
像这样调用这个函数
const char* message = "A word: %s and a number %d";
const int bufferLength = 1024;
char buffer[bufferLength];
int formattedMsgLen = formatString(message, buffer, bufferLength, "cheese", 4);
会立即导致程序崩溃。如果我在
之前将缓冲区 memset 为 0memset(buffer, 0, 1024); // We know sizeof(char) == 1
这被写入缓冲区:
"A word: A word: and a number 1024".
这是完全错误的...
但是,如果我将函数更改为采用结合了前三个参数的结构
struct Message
{
const char* msg;
char* buffer;
int bufferLength;
};
int formatString(Message msg, ...)
{
int length = 0;
if (msg.msg != nullptr) {
va_list args;
va_start(args, msg);
length = vsnprintf_s(msg.buffer, msg.bufferLength, msg.bufferLength, msg.msg, args);
va_end(args);
}
return length;
}
像这样调用新函数时:
const int bufferLength = 1024;
char buffer[bufferLength];
Message msg;
msg.buffer = buffer;
msg.msg = "A word: %s and a number %d";
msg.bufferLength = bufferLength;
int formattedMsgLen = formatString(msg, "cheese", 4);
写入缓冲区:
"A word: cheese and a number 4"
哪个是正确的,这就是我所期望的。我认为您之前只能将 vaargs 与只有一个参数的函数一起使用吗?我认为情况并非如此,因为下面的函数有多个第一个参数
int fprintf(FILE *, const char *fmt, ...);
int sprintf(char *s, const char *fmt, ...);
这可能是编译器中的错误吗?然而不太可能....
可能不是,我做了一些愚蠢的事情,但我肯定对正在发生的事情感到困惑。如果有人能对此有所了解,我将不胜感激。
谢谢!
va_start()
必须在可变参数列表之前使用 last 参数的名称调用:
int formatString(const char* msg, char* buffer, int bufferLength, ...)
{
// ...
va_list args;
// va_start(args, msg); <-- WRONG!
va_start(args, bufferLength);
// ...
}