如何将CString传递给格式string%s?

class MyString { public: MyString(const std::wstring& s2) { s = s2; } operator LPCWSTR() const { return s.c_str(); } private: std::wstring s; }; int _tmain(int argc, _TCHAR* argv[]) { MyString s = L"MyString"; CStringW cstring = L"CString"; wprintf(L"%s\n", (LPCWSTR)cstring); // Okay. Becase it has an operator LPCWSTR() wprintf(L"%s\n", cstring); // Okay, fine. But how? wprintf(L"%s\n", (LPCWSTR)s); // Okay. fine. wprintf(L"%s\n", s); // Doesn't work. Why? It prints gabage string like "?." return 0; } 

如何将CString传递给格式string%s?

顺便说一句, MSDN说 (这很奇怪)

在variables参数函数中使用CString对象
将CString显式转换为LPCTSTRstring,如下所示:

 CString kindOfFruit = "bananas"; int howmany = 25; printf( "You have %d %s\n", howmany, (LPCTSTR)kindOfFruit ); 

CString是专门设计的,它只包含一个指向缓冲区类中的字符串数据的指针。 它通过值传递给printf,然后在格式化字符串中看到“%s”时将其作为指针处理。

它最初只是碰巧和printf一起工作,但后来被保留为类接口的一部分。

  wprintf(L"%s\n", (LPCWSTR)cstring); // Okay. It's been cast to a const wchar_t*. wprintf(L"%s\n", cstring); // UNDEFINED BEHAVIOUR wprintf(L"%s\n", (LPCWSTR)s); // Okay, it's a const wchar_t*. wprintf(L"%s\n", s); // UNDEFINED BEHAVIOUR 

你可以传给这个函数的唯一的东西是const wchar_t* 任何其他的是未定义的行为。 传递CString只是恰好工作。

有一个原因是iostream是用C ++开发的,这是因为这些可变参数函数是非常不安全的,所以永远不会被使用。 哦,CString也是一个罪恶,因为很多原因,坚持std::wstringcout / wcout无论你在哪里。

CString有一个指针作为第一个成员:

 class CStringA { char* m_pString; }; 

虽然它不是char* (即使是ANSI CString),它也差不多是一样的。 当你将CString对象传给任何printf函数族(包括你的自定义实现,如果有的话),你传递的是CString对象(在堆栈上)。 %s解析导致它读取,就好像它是一个指针 – 在这种情况下(这是第一个字节的数据是m_pString ),这是一个有效的指针。

一般来说这是不确定的行为。 根据这篇文章, Visual C ++只是调用从CString到POD类型的转换来覆盖你 – 这是允许的未定义行为的实现。