vswprintf return -1的问题

本文详细描述了在使用vswprintf函数处理变参格式字符串时遇到的问题及解决方案,特别针对不同平台上的表现差异进行了深入分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做一个变参函数的时候,format的时候总是遇到问题。vswprintf()这个方法总是返回-1. 问题代码如下:

#include <stdio.h>
#include <stdarg.h>

void vout(wchar_t *, wchar_t *, ...);

wchar_t *format3 = L"%ls  %d  %ls";
wchar_t *format5 = L"%ls  %d  %ls  %d  %ls";

int main(void)
{
   wchar_t wcstr[100];

   vout(wcstr, 100, format3, L"ONE", 2L, L"THREE");
   printf("%ls\n",wcstr);
   vout(wcstr, 100, format5, L"ONE", 2L, L"THREE", 4L, L"FIVE");
   printf("%ls\n",wcstr);
}

void vout(wchar_t *wcs, wchar_t *fmt, ...)
{
   va_list arg_ptr;

   va_start(arg_ptr, fmt);

   size_t len = vwprintf(fmt, arg_ptr);

   vswprintf(wcs, len, fmt, arg_ptr);
   va_end(arg_ptr);
}

在windows上 vswprintf的返回值是等于len的,但在iOS上却返回-1,后来终于解决了,我把len+1做为第二个参数就正确了。

void vout(wchar_t *wcs, wchar_t *fmt, ...)
{
   va_list arg_ptr;

   va_start(arg_ptr, fmt);

   size_t len = vwprintf(fmt, arg_ptr);

   vswprintf(wcs, len+1, fmt, arg_ptr);
   va_end(arg_ptr);
}



这下完全正确了。

// 增强的日志输出函数 宽字符版本 void OutputLogW(const wchar_t* format, ...) { // 获取当前时间 auto now = std::chrono::system_clock::now(); auto now_time = std::chrono::system_clock::to_time_t(now); auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000; // 格式化时间 std::wstringstream time_ss; time_ss << std::put_time(std::localtime(&now_time), L"%Y-%m-%d %H:%M:%S") << L"." << std::setfill(L'0') << std::setw(3) << now_ms.count(); // 提取文件名(不含路径) // std::wstring filename(file); // size_t pos = filename.find_last_of(L"\\/"); // if (pos != std::wstring::npos) { // filename = filename.substr(pos + 1); // } // 处理变参数 va_list args; va_start(args, format); // 获取变参长度 int len = _vscwprintf(format, args) + 1; // +1 for '\0' if (len <= 0) { va_end(args); return; } // 分配缓冲区 std::wstring buffer; buffer.resize(len); vswprintf_s(&buffer[0], len, format, args); buffer.resize(len - 1); // 移除末尾的null va_end(args); // 构建完整日志消息 std::wstringstream fullMsg; fullMsg << L"[" << time_ss.str() << L"] " << L"[" << file << L":" << line << L"] " << L"[" << function << L"] " << buffer; // 输出到控制台 std::wcerr << fullMsg.str() << std::endl; // 输出到调试器(Windows) #ifdef _WIN32 OutputDebugStringW(fullMsg.str().c_str()); OutputDebugStringW(L"\n"); #endif }完善为日志宏定义为准 #define LOGW(...) OutputLogW(L"[%s:%s:%d] %s",__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
最新发布
08-10
<think>好的,我需要解决用户遇到的C4996编译错误,具体是关于vswprintf函数的问题。用户想了解如何继续使用传统的Microsoft版本函数,而不遵循ISO C标准。根据提供的引用内容,错误是因为Visual C++ 2005之后,swprintf等函数遵循了ISO C标准,导致参数类型变化,从而出现兼容性问题。 首先,我要确认错误的原因。引用[1]、[3]、[4]都指出,swprintf现在需要size_t类型的第二个参数count,而旧版本可能使用不同的参数类型。用户代码中可能使用的是旧的非标准参数形式,所以编译器报错C4996。解决方案之一是在代码中定义宏_CRT_NON_CONFORMING_SWPRINTFS,以强制使用旧的非标准行为,如引用[1]和[4]所述。另一个方法是修改代码,使用新的符合标准的参数类型,但这可能涉及较多的代码改动。 接下来,我需要整理具体的解决步骤。首先,在包含头文件之前定义宏,通常在代码开头或项目设置中添加。例如,在代码顶部添加#define _CRT_NON_CONFORMING_SWPRINTFS。另外,用户提到的是vswprintf,可能需要确认是否适用相同的宏,或者是否需要其他宏定义。引用[2]中提到了针对不同函数的处理,但这里主要讨论的是swprintf,可能vswprintf的解决方式类似。 另外,引用中提到的编译选项,如#pragma warning(disable:4996),可以临时禁用警告,但这不是推荐的做法,因为可能隐藏其他潜在问题。所以建议优先使用宏定义的方法。 还需要提醒用户,微软未来可能移除旧行为,因此长期建议是迁移到符合新标准的代码。例如,检查所有使用swprintf和vswprintf的地方,将参数类型改为size_t,并确保缓冲区大小正确。 总结步骤:1. 定义宏以启用旧行为;2. 修改代码使用新标准;3. 临时禁用警告(不推荐)。需要详细说明每个步骤的具体操作,并给出代码示例,比如如何在代码中添加宏定义,或者如何修改函数参数。同时,引用相关引用来源,如引用[1]、[3]、[4]中的说明,来支持解决方案的正确性。 最后,生成相关问题,可能涉及其他兼容性错误、宏定义的使用方法,或ISO C标准与微软扩展的区别等。</think>### 解答:解决C4996错误与兼容`vswprintf`的传统用法 #### **问题原因分析** 在Visual C++ 2005及更高版本中,`swprintf`和`vswprintf`等函数遵循了ISO C标准,要求第二个参数`count`为`size_t`类型(例如:`int`改为`size_t`)。若代码中使用旧版Microsoft的非标准参数定义(如`count`为`int`),会触发编译错误`C4996`,提示函数行为已变更[^1][^3][^4]。 --- #### **解决方案** 以下是两种主要解决方式: --- ##### **方法1:强制启用旧版非标准行为** 在代码中**定义宏**`_CRT_NON_CONFORMING_SWPRINTFS`,以强制编译器使用旧版函数实现。 **步骤**: 1. 在包含相关头文件(如`<stdio.h>`或`<wchar.h>`)**之前**添加宏定义: ```c #define _CRT_NON_CONFORMING_SWPRINTFS #include <stdio.h> // 其他头文件... ``` 2. 重新编译代码,错误将消失。 **注意**:此方法仅适用于短期兼容,微软未来可能移除旧版行为[^4]。 --- ##### **方法2:修改代码适配ISO C标准** 长期建议修改代码,使用新标准的函数签名: ```c int swprintf(wchar_t* buffer, size_t count, const wchar_t* format, ...); ``` **示例修改**: 旧代码可能为: ```c swprintf(buf, 100, L"Value: %d", num); // 第二个参数原为int类型 ``` 修改后: ```c swprintf(buf, (size_t)100, L"Value: %d", num); // 显式转换为size_t ``` --- ##### **方法3(不推荐):禁用特定警告** 临时屏蔽警告`C4996`,但可能隐藏其他潜在问题: ```c #pragma warning(disable:4996) ``` --- #### **引用说明** - 定义宏`_CRT_NON_CONFORMING_SWPRINTFS`可恢复旧版`swprintf`行为[^4]。 - 微软明确建议最终适配新标准,因旧行为可能被移除[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值