简体   繁体   English

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

[英]How can CString be passed to format 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;
}

How can CString be passed to format string %s?如何将 CString 传递给格式字符串 %s?

By the way, MSDN says (it's weird)顺便说一句, MSDN 说(这很奇怪)

To use a CString object in a variable argument function在变量参数 function 中使用 CString object
Explicitly cast the CString to an LPCTSTR string, as shown here:将 CString 显式转换为 LPCTSTR 字符串,如下所示:

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

CString is specifically designed such that it only contains a pointer that points to the string data in a buffer class. CString 是专门设计的,它只包含一个指向缓冲区 class 中的字符串数据的指针。 When passed by value to printf it will be treated as a pointer when seeing the "%s" in the format string.当按值传递给 printf 时,当在格式字符串中看到“%s”时,它将被视为指针。

It originally just happened to work with printf by chance, but this has later been kept as part of the class interface.它最初只是碰巧与 printf 一起工作,但后来被保留为 class 接口的一部分。


This post is based on MS documentation long since retired, so I cannot link to their promise that they will continue to make this work.这篇文章基于早已退休的 MS 文档,所以我无法链接到他们的 promise,他们将继续完成这项工作。

However, before adding more downvotes please also read this blog post from someone sharing my old knowledge:但是,在添加更多反对票之前,还请阅读分享我旧知识的人的这篇博文:

Big Brother helps you大哥帮你

    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

The only thing you can pass to this function for %s is a const wchar_t* .对于%s ,您唯一可以传递给此 function 的是const wchar_t* Anything else is undefined behaviour.其他任何事情都是未定义的行为。 Passing the CString just happens to work.传递 CString 恰好可以工作。

There's a reason that iostream was developed in C++, and it's because these variable-argument functions are horrifically unsafe, and shoud never be used. iostream在 C++ 中开发是有原因的,因为这些可变参数函数非常不安全,不应该使用。 Oh, and CString is pretty much a sin too for plenty of reasons, stick to std::wstring and cout / wcout wherever you can.哦,由于很多原因,CString 也几乎是一种罪过,尽可能坚持使用std::wstringcout / wcout

CString has a pointer as the first member: CString有一个指针作为第一个成员:

class CStringA
{
      char* m_pString;
};

Though it is not char* (even for ANSI CString), it is more or less the same thing.虽然它不是char* (即使是 ANSI CString),但它或多或少是一回事。 When you pass CString object to any of printf-family of functions (including your custom implementation, if any), you are passing CString object (which is on stack).当您将 CString object 传递给任何 printf 系列函数(包括您的自定义实现,如果有的话)时,您将传递 CString object(在堆栈上)。 The %s parsing causes it it read as if it was a pointer - which is a valid pointer in this case (the data at very first byte is m_pString ). %s解析使它读起来就好像它是一个指针 - 在这种情况下这是一个有效的指针(第一个字节的数据是m_pString )。

Generally speaking it's undefined behavior.一般来说,这是未定义的行为。 According to this article Visual C++ just invokes the conversion from CString to a POD type to cover you - that is permissible implementation of undefined behavior.根据这篇文章Visual C++ 只是调用从CString到 POD 类型的转换来覆盖你 - 这是未定义行为的允许实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM