浅谈c++字符串——3 MFC字符串

3 MFC字符串

3.1 MFC下的常用字符串数据类型表示的含义

L:Long  长  P:Point  指针  C:Const  常量  W:Wchar_t  宽字符  T:TCHAR STR:String  字符串

在看看MFC下各种数据类型的定义:

typedef char *LPSTR;typedef const char *LPCSTR;

typedef wchar_t *LPWSTR; typedef const wchar_t *LPCWSTR; typedef wchar_t WCHAR; #ifdef  UNICODE typedef  LPCWSTR  LPCTSTR; typedef  WCHAR   TCHAR;

#else typedef  LPCSTR  LPCTSTR;

typedef  char  TCHAR;

3.2 MFC下提供的ATL转换宏(宽字节 <-> 多字节)

T2A   T2W   T2CA  T2CW         W2A   W2CA   W2T   W2CT         A2W   A2CW   A2T   A2CT 

T:TCHAR 2:To C:CONST A:CHAR(ANSI)   W:WCHAR

先到atlconv.h头文件下看看这些宏的定义,

3.2.1 USES_CONVERSION

注意int _convert; (_convert);这种用法是为了屏蔽编译器的警告:未引用的局部变量。。。

#ifndef _DEBUG
#define USES_CONVERSION int _convert; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw; (_lpw); LPCSTR _lpa; (_lpa)
#else
#define USES_CONVERSION int _convert = 0; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw = NULL; (_lpw); LPCSTR _lpa = NULL; (_lpa)
#endif

可见,USES_CONVERSION宏定义了一些转换所需要的变量,如_convert。所以使用那些宏的时候必须加上该宏。

3.2.2 以A2W为例说明宏转换过程

3.2.2.1 A2W多字节转换为宽字节

这里就用到了USES_CONVERSION宏定义的_convert变量

#define A2W(lpa) (\
((_lpa = lpa) == NULL) ? NULL : (\
_convert = (lstrlenA(_lpa)+1),\
(INT_MAX/2<_convert)? NULL :  \
ATLA2WHELPER((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, _acp)))

3.2.2.2 ATLA2WHELPER 多字节转换为宽字节

#define ATLA2WHELPER AtlA2WHelper

AtlA2WHelper实际上还是在调用MultiByteToWideChar,即多字节转换为宽字节

Ret_opt_z_cap_(nChars) inline LPWSTR WINAPI AtlA2WHelper(_Out_z_cap_(nChars) LPWSTR lpw, _In_z_ LPCSTR lpa, _In_ int nChars, _In_ UINT acp) throw()
{

    ATLASSERT(lpa != NULL);
    ATLASSERT(lpw != NULL);
    if (lpw == NULL || lpa == NULL)
        return NULL;
    *lpw = '\0';
    int ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
    if(ret == 0)
    {
        ATLASSERT(FALSE);
    return NULL;
    }  
    return lpw;
}

3.2.2.3 alloca 从堆上分配以字节为单位的内存

#define alloca  _alloca

_alloca:该函数从堆上分配以字节为单位的内存,返回void *

void *_alloca(
size_t size
);

3.2.2.4 用法举例

USES_CONVERSION;//USES_CONVERSION是ATL中的一个宏定义,用于编码转换,它定义了转换宏所需的一些局部变量

WCHAR *pWch = L"WCHAR* TO CHAR*";

CHAR *pCh = W2A(pWch);

TCHAR *pTch = _T("TCHAR* TO CHAR*");

CHAR *pCh2 = T2A(pTch);

3.2.3 USES_CONVERSION使用注意

使用USES_CONVERSION一定要小心,它们从堆栈上分配内存,直到调用它的函数返回,该内存不会被释放。如果在一个循环中,这个宏被反复调用几万次,将不可避免的产生stackoverflow。但是考虑到栈空间的尺寸(默认2M),使用时要注意几点:

1、只适合于进行短字符串的转换;

2、不要试图在一个次数比较多的循环体内进行转换;

3、不要试图对字符型文件内容进行转换,因为文件尺寸一般情况下是比较大的;

4、对情况 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();

5、将字符转换封装到函数里面

void DoA2W()
{
     USES_CONVERSION;
     DoSomething(A2W("SomeString"));
}

3.3 CString

Header

Use for

 

cstringt.h

MFC-only string objects

必须使用在MFC程序中,需要MFC静态或动态库并包含头文件<afxwin.h>

atlstr.h

Non-MFC string objects

可以使用在非MFC程序中,只需包含<atlstr.h>非常好用,支持Unicode字符集

具体MSDN中有详细的介绍

3.4 浅谈_T、_TEXT、TEXT、L

MSDN中对于L的说明有一大堆英文,不过主要的就是:L是用来标志一个字符(串)为宽字符(串)

宽字符和多字节字符的说明如下:(引用自网络)

宽字符,wide character,该字符集内每个字符使用相同的位长;

多字节字符,multibyte character,每个字符可以是一到多个字节不等,而某个字节序列的字符值由字符串或流(stream)所在的环境背景决定。

当你在VS2005以上版本的IDE工作时,可以选择工作于这两种不同的编码方式下,而在Unicode方式下,则要对字符(串)常量前添加L来告诉编译器它是宽字符

而MS为我们定义了好几个相关的宏,下面来一一说明:

_T            //定义于tchar.h

_TEXT      //同样定义于tchar.h,具体如下:

#define _T(x)       __T(x)

#define _TEXT(x)    __T(x)

 

#ifdef  _UNICODE

#define __T(x)      L ## x     //第210行

#else

#define __T(x)      x          //第858行

#endif

TEXT     //定义于winnt.h

#define TEXT(quote) __TEXT(quote)

 

#ifdef  UNICODE                     

#define __TEXT(quote) L##quote      

#else   /* UNICODE */               

#define __TEXT(quote) quote         

#endif /* UNICODE */   

当我看到这里的时候,一下子头晕了,不知道大家有没有注意到下面两个问题:

1.这三个宏分别在两个不同的文件被定义,看上去一个是运行时的头文件,一个是Win的头文件

2.前面两个根据_UNICODE来确定宏内容,另一个则是根据UNICODE

那如果要同时使用这三个宏的话,那不是要同时定义_UNICODE和UNICODE?带着问题,我把项目的属性修改一下

当设置为Unicode编码的时候,编译器命令选项中的确同时加入了_UNICODE和UNICODE

看来这应该又是MS的历史遗留问题拉,搜索一下才发现:(引自网络)

Jeffrey Richter在《Windows核心编程》中说,_UNICODE宏用于C运行期头文件,而UNICODE宏则用于Windows头文件.当编译源代码模块时,通常必须同时定义这两个宏.

看IDE自动生成的代码,大都使用TEXT这个,应该是因为IDE生成的都是基于Win的代码,使用这个也很正常吧

从上面的分析可得:

这几个宏的效果都是一个的,还是建议大家有事没事都加上其中一个(_T、_TEXT、TEXT)

而L嘛,个人认为还是不要在代码中直接使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值