Это работает, потому что первый элемент класса CString является указателем на массив символов. На самом деле единственное поле в CString — это указатель на массив строк. Этот класс использует некоторые приемы, чтобы скрыть внутренние данные (такие как длина строки, зарезервированный размер буфера и т. д.), выделяя один большой буфер, а затем оставляя единственный указатель класса, указывающий на массив символов, чтобы добраться до этих внутренних полей данных, он сдвигает этот указатель на известное значение. компенсировать.
Что вам нужно сделать, так это вызвать s.GetBuffer(0); или (LPCTSTR); но используя его как
sprintf(z2, "%s", ss);
был разрешен по замыслу создателей MFC, конечно, он работает под Windows, на других платформах может произойти сбой.
[править после комментариев]
ваш код будет безопаснее, если вместо приведений в стиле C, таких как (LPCTSTR)s
, вы будете использовать приведение C++: static_cast<LPCTSTR>(s);
. Но очень скоро вы обнаружите, что ваш код становится некрасивым со всеми этими static_cast-ами, особенно если ваши sprintf-ы имеют много параметров. Насколько я помню (и, на мой взгляд), по дизайну приведения в стиле С++ предназначены для того, чтобы вы переосмыслили свой дизайн, чтобы вообще не использовать приведения. В вашем случае вместо использования sprintf вы должны использовать std::wstringstream (при условии, что вы используете сборку UNICODE):
#include<sstream>
std::wostream & operator<< (std::wostream &out, CString const &s) {
out << s.GetString();
return out;
}
int main(){
CString s = _T("test");
std::wstringstream ss;
ss << s; // no cast required, no UB here
std::wcout << ss.str();
return 0;
}
person
marcinj
schedule
26.02.2014