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::wstring
和cout
/ wcout
无论你在哪里。
CString
有一个指针作为第一个成员:
class CStringA { char* m_pString; };
虽然它不是char*
(即使是ANSI CString),它也差不多是一样的。 当你将CString对象传给任何printf函数族(包括你的自定义实现,如果有的话),你传递的是CString对象(在堆栈上)。 %s
解析导致它读取,就好像它是一个指针 – 在这种情况下(这是第一个字节的数据是m_pString
),这是一个有效的指针。
一般来说这是不确定的行为。 根据这篇文章, Visual C ++只是调用从CString
到POD类型的转换来覆盖你 – 这是允许的未定义行为的实现。