c – sprintf如何与CString和std :: string一起使用

CString s = "test";
std::string ss = "test";

char z[100];
sprintf(z,"%s",ss.c_str()); // z = "test"  : OK

char z2[100];
sprintf(z2,ss); // z2 = "(null)" : OK. undefined behavior is expected

char z3[100];
sprintf(z3,s); // z3 = "test" : How is this possible ?!

任何人都可以解释CString如何与sprintf正常工作?

解决方法

它的工作原理是因为CString类的第一个元素是一个指向char数组的指针.实际上,CString中唯一的字段是指向字符串数组的指针.这个类使用一些技巧来隐藏内部数据(如字符串长度,保留缓冲区大小等),方法是分配一个大缓冲区,然后将唯一的类指针指向char数组,以获取那些内部数据字段,它通过已知的方式移动此指针偏移.

你应该做的是调用s.GetBuffer(0);或(LPCTSTR)s;但用它作为

sprintf(z2,ss);

被MFC创建者设计允许,当然它可以在Windows下在其他平台上运行,它可能会崩溃.

[评论后编辑]

你的代码将更安全,如果不是像(LPCTSTR)那样的c风格的演员表,你将使用c cast: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;
}

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...