CString与const char*互转 深入详解

很多网上的文章只讲了用法,但是没有真正深入地去讲CString转换为啥可以这样做

CString其实是一个模板CStringT的别名

typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;

根据工程设置是Unicode还是多字节,存放的字符串TCHAR不同

这里假定大家都了解Unicode编程

CStringT的基类是CSimpleStringT

template< typename BaseType, class StringTraits >
class CStringT :
	public CSimpleStringT< BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits >

CSimpleStringT重载了操作符

    operator PCXSTR() const throw()
	{
		return( m_pszData );
	}

PCXSTR在多字节的环境下,其实就是const char*,在Unicode下是const wchar_t*

一、多字节环境

我们做一下测试,

void CMFCApplication4Dlg::OnBnClickedButton2()
{
    CString str("测试");
    const char *p = (const char *)str;
}

笔者这里是VS2012

菜单->"调试” -》“窗口”-》反汇编看一下,证明上面的代码确实是调用重载操作符

    CString str("测试");
005E8BBD  push        1  
005E8BBF  lea         ecx,[str]  
005E8BC2  call        ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >::__autoclassinit (05C885Ch)  
005E8BC7  push        0BC9248h  
005E8BCC  lea         ecx,[str]  
005E8BCF  call        ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > (05C456Dh)  
    const char *p = (const char *)str;
005E8BD4  lea         ecx,[str]  
005E8BD7  call        ATL::CSimpleStringT<char,0>::operator char const * (05D590Dh)  
005E8BDC  mov         dword ptr [p],eax  
}

 OK,那么上面的写法,我们可以简单改成

 

void CMFCApplication4Dlg::OnBnClickedButton2()
{
    CString str("测试");
    const char *p = str;
}

反汇编看一下,程序默认调用了操作符重载

  CString str("测试");
00558BBD  push        1  
00558BBF  lea         ecx,[str]  
00558BC2  call        ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >::__autoclassinit (053885Ch)  
00558BC7  push        0B39248h  
00558BCC  lea         ecx,[str]  
00558BCF  call        ATL::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > >::CStringT<char,StrTraitMFC<char,ATL::ChTraitsCRT<char> > > (053456Dh)  
    const char *p = str;
00558BD4  lea         ecx,[str]  
00558BD7  call        ATL::CSimpleStringT<char,0>::operator char const * (054590Dh)  
00558BDC  mov         dword ptr [p],eax  
}

 也就是说在多字节的环境下,我们可以简单粗暴地把CString传给那个函数参数是const char*的变量

而下面这种直接把CString转成char *却是不行的,因为没有相关的操作符重载

CString与const char*互转 深入详解

 

二、Unicode环境下

void CMFCApplication4Dlg::OnBnClickedButton2()
{
    CString str(_T("测试"));
    const wchar_t *p = (const wchar_t *)str;
}

 反汇编下

   CString str(_T("测试"));
01158C8D  push        1  
01158C8F  lea         ecx,[str]  
01158C92  call        ATL::CStringT<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::__autoclassinit (0112E244h)  
01158C97  push        173B298h  
01158C9C  lea         ecx,[str]  
01158C9F  call        ATL::CStringT<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::CStringT<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t> > > (0113FFE4h)  
    const wchar_t *p = (const wchar_t *)str;
01158CA4  lea         ecx,[str]  
01158CA7  call        ATL::CSimpleStringT<wchar_t,0>::operator wchar_t const * (011427DFh)  
01158CAC  mov         dword ptr [p],eax  
}

说明在Unicode编程环境下,不能简单粗暴地把CString传给那个函数参数是const char*的变量

三、适配2种不同字符环境的写法

void CMFCApplication4Dlg::OnBnClickedButton2()
{
    CString str(_T("测试"));
    LPCTSTR p = (LPCTSTR)str;
}

好吧,笔者也写了很多年的MFC程序,今天终于花点时间把CString的面纱解开,

大家有看懂的,帮忙点赞一下,谢谢!

上一篇:python接口自动化(十二)--https请求(SSL)(详解)


下一篇:Vue3.0+Element-plus项目框架搭建(三):初始化项目结构