rmi*_*rmi 7 c++ mfc cstring visual-studio-2008 visual-c++
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 ?!
Run Code Online (Sandbox Code Playgroud)
谁能解释一下如何CString正常使用sprintf?
它的工作原理是因为CString类的第一个元素是一个指向char数组的指针.实际上,CString中唯一的字段是指向字符串数组的指针.此类使用一些技巧通过分配一个大的缓冲器,然后在离开仅类指针隐藏内部数据(像字符串长度,保留的缓冲器大小,等等)所指向的字符数组,以获得对这些内部数据字段它通过已知的移动该指针偏移.
你应该做的是调用s.GetBuffer(0); 或(LPCTSTR)s; 但用它作为
sprintf(z2, "%s", ss);
Run Code Online (Sandbox Code Playgroud)
被MFC创建者设计允许,当然它可以在Windows下在其他平台上运行,它可能会崩溃.
[评论后编辑]
你的代码将更安全,如果不是像(LPCTSTR)s你将使用c ++ cast 的c风格的演员:static_cast<LPCTSTR>(s);.但是很快你就会发现你的代码在所有这些static_cast-s中都很难看,特别是如果你的sprintf-s有很多参数的话.这是我记忆(在我看来)的设计,c ++风格的演员表旨在让你重新考虑你的设计,根本不使用演员表.在你的情况下,你应该使用std :: wstringstream而不是使用sprintf(假设你使用UNICODE构建):
#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;
}
Run Code Online (Sandbox Code Playgroud)
这种行为CString似乎并非正式支持微软(它依赖于实现细节的CString,这似乎在制作像你举一个案件工作,但在将来可能会改变).
请注意,强制转换CString PCXSTR操作符的MSDN文档如下:
Run Code Online (Sandbox Code Playgroud)// 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);
实际上演员阵容很糟糕,因为它是一个C风格的演员阵容.我会使用C++ - 样式转换static_cast<PCWSTR>(string)或仅使用CString::GetString()方法.
另一个MSDN文档页面读取(强调我的):
在变量参数函数中使用CString对象
一些C函数采用可变数量的参数.一个值得注意的例子是
printf_s.由于声明了这种函数的方式,编译器无法确定参数的类型,也无法确定要对每个参数执行哪种转换操作.因此,在将对象传递给采用可变数量参数的函数时,必须使用显式类型转换CString.要CString在变量参数函数中使用对象,请显式CString转换为LPCTSTR字符串,如以下示例所示.Run Code Online (Sandbox Code Playgroud)CString kindOfFruit = _T("bananas"); int howmany = 25; _tprintf_s(_T("You have %d %s\n"), howmany, (LPCTSTR)kindOfFruit);
同样,我更喜欢C++风格 static_cast<PCTSTR>的MSDN文档中使用的C风格的转换.或者打电话CString::GetString()会很好.
另请参阅此博客文章:老大哥帮助您.
| 归档时间: |
|
| 查看次数: |
5845 次 |
| 最近记录: |