Как можно передать CString для форматирования строки% 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 в строку формата% s?

Кстати, MSDN говорит (это странно)

  

Использование объекта CString в функции переменного аргумента
  Явно приведите CString к строке LPCTSTR, как показано здесь:

CString kindOfFruit = "bananas";
int      howmany = 25;
printf( "You have %d %s\n", howmany, (LPCTSTR)kindOfFruit ); 
12 голосов | спросил Benjamin 7 J000000Thursday11 2011, 14:09:59

4 ответа


0

CString специально разработан таким образом, что он содержит только указатель, который указывает на строковые данные в классе буфера. При передаче по значению в printf он будет считаться указателем при отображении «% s» в строке формата.

Изначально он просто случайно работал с printf, но позже он был сохранен как часть интерфейса класса.


Этот пост основан на документации MS, давно вышедшей на пенсию, поэтому я не могу сослаться на их обещание, что они продолжат эту работу.

Однако, прежде чем добавлять больше отрицательных голосов, пожалуйста, прочитайте этот блог от кого-то, кто делится моими старыми знаниями:

Большой брат помогает вам

ответил Bo Persson 7 J000000Thursday11 2011, 14:54:59
0
    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::wstring и cout /wcout везде, где вы можете.

ответил Puppy 7 J000000Thursday11 2011, 14:53:44
0

CString имеет указатель в качестве первого члена:

class CStringA
{
      char* m_pString;
};

Хотя это не char* (даже для ANSI CString), это более или менее одно и то же. Когда вы передаете объект CString любой из функций семейства printf (включая вашу пользовательскую реализацию, если таковая имеется), вы передаете объект CString (который находится в стеке). Синтаксический анализ %s приводит к тому, что он читается так, как если бы он был указателем - в данном случае это действительный указатель (данные в самом первом байте m_pString).

ответил Ajay 14 J000000Thursday11 2011, 12:04:29
0

Вообще говоря, это неопределенное поведение. Согласно этой статье Visual C ++ просто вызывает преобразование из CString к типу POD, чтобы покрыть вас - это допустимая реализация неопределенного поведения.

ответил sharptooth 7 J000000Thursday11 2011, 15:08:59

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132