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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6608942/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:25:33  来源:igfitidea点击:

How can CString be passed to format string %s?

c++windowsstringtype-conversionstring-formatting

提问by Benjamin

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
Explicitly cast the CString to an LPCTSTR string, as shown here:

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

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

采纳答案by Bo Persson

CString is specifically designed such that it only contains a pointer that points to the string data in a buffer class. When passed by value to printf it will be treated as a pointer when seeing the "%s" in the format string.

CString 是专门设计的,因此它只包含一个指向缓冲区类中字符串数据的指针。当按值传递给 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 一起使用,但后来被保留为类接口的一部分。



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 文档,因此我无法链接到他们将继续进行这项工作的承诺。

However, before adding more downvotes please also read this blog post from someone sharing my old knowledge:

但是,在添加更多downvotes之前,还请阅读分享我旧知识的人的这篇博文:

Big Brother helps you

大哥帮你

回答by Puppy

    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 onlything you can pass to this function for %sis a const wchar_t*. Anything else is undefined behaviour. Passing the CString just happens to work.

您可以传递给此函数的唯一内容%sconst wchar_t*. 其他任何行为都是未定义的行为。传递 CString 恰好可以工作。

There's a reason that iostreamwas developed in C++, and it's because these variable-argument functions are horrifically unsafe, and shoud never be used. Oh, and CString is pretty much a sin too for plenty of reasons, stick to std::wstringand cout/wcoutwherever you can.

iostream用 C++ 开发是有原因的,这是因为这些可变参数函数非常不安全,永远不应该使用。哦,出于很多原因,CString 也几乎是一种罪过,只要你能坚持std::wstringcout/wcout就可以了。

回答by Ajay

CStringhas 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. 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). The %sparsing 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).

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

回答by sharptooth

Generally speaking it's undefined behavior. According to this articleVisual C++ just invokes the conversion from CStringto a POD type to cover you - that is permissible implementation of undefined behavior.

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