如何将CString传递给格式字符串%s?

时间:2011-07-07 10:09:59

标签: c++ windows string type-conversion string-formatting

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传递给格式字符串%s?

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

  

在变量参数函数中使用CString对象
  将CString显式地转换为LPCTSTR字符串,如下所示:

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

4 个答案:

答案 0 :(得分:12)

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

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


这篇文章基于MS文档很久以来已经退休,因此我无法链接到他们将继续使其工作的承诺。

然而,在添加更多downvotes之前,请阅读分享我以前的知识的人的博客文章:

Big Brother helps you

答案 1 :(得分:6)

    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

您可以为%s传递给此函数的const wchar_t*。其他任何东西都是未定义的行为。传递CString恰好可以正常工作。

有一个原因是iostream是用C ++开发的,这是因为这些变量参数函数非常不安全,并且永远不会被使用。哦,CString也是一个很好的理由,无论你在哪里都坚持std::wstringcout / wcout

答案 2 :(得分:3)

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

class CStringA
{
      char* m_pString;
};

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

答案 3 :(得分:2)

一般来说,这是未定义的行为。根据{{​​3}} Visual C ++只是调用从CString到POD类型的转换来覆盖你 - 这是允许的未定义行为的实现。