C++ sprintf如何使用CString和std::string
有人能解释一下C++ sprintf如何使用CString和std::string,c++,visual-c++,visual-studio-2008,mfc,cstring,C++,Visual C++,Visual Studio 2008,Mfc,Cstring,有人能解释一下CString如何与sprintf一起正常工作吗?因为CString类的第一个元素是指向char数组的指针。实际上,CString中唯一的字段是指向字符串数组的指针。该类使用一些技巧隐藏内部数据(如字符串长度、保留缓冲区大小等),方法是分配一个大缓冲区,然后将唯一的类指针指向char数组,以获取这些内部数据字段。它将该指针移动已知偏移量 您应该做的是调用s.GetBuffer(0);或(LPCTSTR)s;但是把它当作 CString s = "test"; std::string
CString
如何与sprintf
一起正常工作吗?因为CString类的第一个元素是指向char数组的指针。实际上,CString中唯一的字段是指向字符串数组的指针。该类使用一些技巧隐藏内部数据(如字符串长度、保留缓冲区大小等),方法是分配一个大缓冲区,然后将唯一的类指针指向char数组,以获取这些内部数据字段。它将该指针移动已知偏移量
您应该做的是调用s.GetBuffer(0);或(LPCTSTR)s;但是把它当作
CString s = "test";
std::string ss = "test";
char z[100];
sprintf(z, "%s", ss.c_str()); // z = "test" : OK
char z2[100];
sprintf(z2, "%s", ss); // z2 = "(null)" : OK. undefined behavior is expected
char z3[100];
sprintf(z3, "%s", s); // z3 = "test" : How is this possible ?!
是MFC创建者设计的,当然它可以在Windows下工作,在其他平台上可能会崩溃
[评论后编辑]
如果不是C样式的转换,如
#包括
std::wostream&operator微软似乎没有正式支持CString
的这种行为(它依赖于CString
的实现细节,这些细节似乎是精心设计的,可以在您引用的情况下工作,但将来可能会改变)
请注意:
事实上,这是一个糟糕的演员阵容,因为这是一个C风格的演员阵容。我会使用C++风格的强制转换静态强制转换(string)
或者只使用CString::GetString()
方法
另一条是(我的重点):
在变量参数函数中使用CString对象
有些C函数的参数数量可变。著名的
例如printf\u s
。因为这种函数是
声明时,编译器无法确定参数的类型和
无法确定要对每个对象执行的转换操作
论点因此,传递时必须使用显式类型转换
函数的CString
对象,该函数具有可变的
参数。要在变量参数函数中使用CString
对象,
显式地将CString
强制转换为LPCTSTR
字符串,如
下面的例子
// If the prototype isn't known or is a va_arg prototype,
// you must invoke the cast operator explicitly. For example,
// the va_arg part of a call to swprintf_s() needs the cast:
swprintf_s(sz, 1024, L"I think that %s!\n", (PCWSTR)strSports);
同样,与MSDN文档中使用的C样式转换相比,我更喜欢C++样式的static_cast
。或者调用CString::GetString()
就可以了
另请参阅此博客文章:
另一个。正确的调用方法是CString::GetString()
,而不是GetBuffer()
。还要注意的是,C风格的强制转换是不好的:请使用C++风格的强制转换:static\u cast(ss)
。更准确地说,在您的情况下,强制转换应该是static\u cast(ss)
,因为您使用的是sprintf()
(而不是TCHAR
这样基于的函数。这样,在Unicode构建(自VS2005以来一直是默认的,CString
实际上是CStringW
)上,强制转换失败,代码无法编译,您可以修复它(而不是将错误参数传递给sprintf()
,并在运行时无声地引入错误).ss
是示例中的std::string
,ITYMs.GetBuffer(0)
等。否则将是ss.c_str()。我不确定OP是否使用UNICODE,据我记忆所及,CString在分配给它时可以隐式地将多字节转换为wchar_t字符串。感谢您对强制转换的详细解释。
#include<sstream>
std::wostream & operator<< (std::wostream &out, CString const &s) {
out << s.GetString();
return out;
}
int main(){
CString s = _T("test");
std::wstringstream ss;
ss << s; // no cast required, no UB here
std::wcout << ss.str();
return 0;
}
// If the prototype isn't known or is a va_arg prototype,
// you must invoke the cast operator explicitly. For example,
// the va_arg part of a call to swprintf_s() needs the cast:
swprintf_s(sz, 1024, L"I think that %s!\n", (PCWSTR)strSports);
CString kindOfFruit = _T("bananas");
int howmany = 25;
_tprintf_s(_T("You have %d %s\n"), howmany, (LPCTSTR)kindOfFruit);