Visual C++调用swprintf_s输出整数警告与结果异常问题
问题根因
第一个swprintf_s调用触发警告、输出异常的核心原因是实参类型和格式占位符要求的类型不匹配,触发可变参数函数的未定义行为。
涉及的问题代码如下:
swprintf_s(g_msgbuf, L"--> val: %llu<--\n", 0xfffffff); OutputDebugString(g_msgbuf); swprintf_s(g_msgbuf, L"--> val: %llu<--\n", 0x100000000); OutputDebugString(g_msgbuf);
编译第一个调用时抛出的警告为:
大小不匹配:调用'swprintf_s'时,第3个参数传入类型为'int',但要求参数类型为'long long'。
警告触发逻辑
- C/C++中不带后缀的整数字面量,类型会根据值的大小自动适配:
0xfffffff对应十进制值为268435455,落在32位有符号int的取值范围(-2147483648 ~ 2147483647)内,因此编译器默认将其识别为4字节长度的int类型。- 格式串中使用的
%llu占位符,要求传入的对应参数必须是8字节长度的unsigned long long类型。编译器做格式串静态检查时,检测到实参宽度、类型和占位符要求不符,就会抛出上述类型不匹配警告。
- 第二个调用无警告的原因:
0x100000000对应十进制值为4294967296,已经超出32位int、32位unsigned int的取值上限,编译器会自动将其推导为8字节长度的整数类型,刚好匹配%llu的参数要求,因此不会触发警告。
输出值异常的原因
swprintf_s属于printf家族的可变参数函数,这类函数不会根据格式符自动对传入的实参做适配性类型转换,只会严格按照格式符指定的字节宽度,从栈空间读取对应长度的数据解析。- 第一个调用传入的实参仅占4字节栈空间,但
%llu会连续读取8字节数据:除了传入的4字节有效值,相邻高地址的4字节是栈上残留的无意义脏数据,两部分拼接成的8字节值被解析为unsigned long long,最终输出和预期完全不符的超大数值34359214650425343。 - 第二个调用传入的实参本身占8字节,
%llu读取的全部是有效数据,因此能正常输出预期值。
修复方案
给第一个整数字面量添加ULL后缀,显式指定其为unsigned long long类型即可,修改后代码如下:
swprintf_s(g_msgbuf, L"--> val: %llu<--\n", 0xfffffffULL);
也可以通过显式强转实现相同效果:
swprintf_s(g_msgbuf, L"--> val: %llu<--\n", (unsigned long long)0xfffffff);
内容的提问来源于stack exchange,提问作者darro911
相关产品推荐
相关产品推荐

