fmt::sprintf的正确使用方法是什么?替换sprintf后代码为何失效?
错误原因
- 你混淆了C标准库
sprintf和fmt库fmt::sprintf的接口约定:- C标准库
sprintf的第一个参数是用于存储格式化结果的目标缓冲区地址 fmt::sprintf不需要传入目标缓冲区,它的返回值是格式化完成的std::string对象
- C标准库
- 你的替换代码既没有把
name数组作为输出目标传入,也没有接收fmt::sprintf的返回值,格式化后的结果没有被存储到name数组中,原有逻辑依赖的name变量完全没有被赋值,因此无法正常运行。
正确使用方式
方案1:直接使用fmt::sprintf返回值(更推荐,无缓冲区溢出风险)
不需要预先定义固定长度的char数组,直接接收返回的std::string即可:
auto type = actor->GetName(); std::string name; if (type.find("AI") != std::string::npos) { name = fmt::sprintf("AI [%dm]", dist); } // 后续如果需要C风格字符串,调用name.c_str()即可
方案2:适配原有char数组逻辑
如果后续代码必须依赖固定长度的char name[0x64]定义,可以使用fmt::format_to_n接口写入预分配的缓冲区:
auto type = actor->GetName(); char name[0x64]; if (type.find("AI") != std::string::npos) { // 写入缓冲区,预留最后1位存放终止符 auto write_res = fmt::format_to_n(name, sizeof(name) - 1, "AI [%dm]", dist); // 手动添加字符串终止符 *write_res.out = '\0'; }
注意事项
- 使用fmt相关接口需要提前引入对应头文件:
#include <fmt/sprintf.h>(用fmt::sprintf时)、#include <fmt/format.h>(用fmt::format_to_n时) fmt::sprintf默认会做格式字符串和参数的类型校验,相比C标准库sprintf安全性更高,不会出现类型不匹配导致的未定义行为。
内容的提问来源于stack exchange,提问作者user17198097
相关产品推荐
相关产品推荐

