ANSI,MBCS和Unicode三种编码方式使用swprintf函数的陷阱

我们可能平时经常使用swprintf这个API函数,其实这个函数存在很容易让人误解的陷阱,有时在我们的程序使用的时候平时不会出现错误,可是这些API函数的误使用可能会产生一些偶然的错误,这些错误是相当的难找的,所以在平时我们写程序就应该对我们每使用的一个API函数都应该足够的了解其正确的用法,就好像是我们把一个CString直接强转为LPTSTR ,这样就会形成潜在的危险,如果我们了解CString的用法,就可以这样更安全的使用:

CString str ;

…..//assume str has contain valid data

LPTSTR lpszBuff =str.GetBuffer(0);

 

swprintf这个函数的陷阱也像上面说的一样,使用不当都存在潜在的危险,所谓知其然知其所以然’,在分析这个API可能存在的陷阱之前,先简单的说一下与之相关的几个概念:

ANSI字符集:single-byte character set (SBCS),就是我们平时说的char ,每个字符是一个字节,’\0’作为字符串的结束符.

MBCS:(multi-byte character set ):有的字符是占两个字节,有的字符是占一个字节,OS提供了一些API对之进行操作,如果是两个字节,包括一个称为”Lead bytes””trail byte”.也是以一个’\0’作为结束符.

Unicode:又称为宽字符,每个字符占两个字节,以两个字节的’\0’结束

以上只是简单的介绍一下,详细的可见: String complete Guide

 

下面进入正题,先看一下这一段代码,猜一下结果是什么:

       wchar_t         strTemp[64];

       swprintf(strTemp,L"%s","ngangche结果");

 

       第一种情况:

              BYTE* pData =(BYTE*) strTemp;

int nLen = _mbslen(pData); //结果是:0x0A

       第二种情况:

                   char* pData =(char*) strTemp;

              int nLen = strlen(pData); //结果是0x0C

 

第三种情况:

         int nLen = wcslen(strTemp);//结果是0x06

 

呵呵,为什么同一段内存,会有这么多不同,你可能在想这段内存到底放的什么,因为这个函数名称是有些让人迷惑的,swprintf ,而不是swprintf而不是sprintf ,可能想到,最后strTemp中应该放的是Unicode字符,而实际放的是什么东西呢,为什么第三种情况结果不是我们想要的10而是6,不用着急,看一下这张图就什么都清楚了:


上面的API用法,并不是Unicode ,你可以看到0x12ff00 ~0x12ff07ASCII :ngangche(8个字符),而后面的两个中文字符:0x12ff08~0x12ff0b是两个中文字符,后面是两个’\0’,所以用_mbslen算出的结果是正确的,10个字符.这个也不是MBCS,因为MBCS是一个’\0’结束.

         第二种情况就很容易了:中文占两个字符正好是12个字符

         第三种情况也很容易理解12/2 = 6个字符.

        

         看来这个API函数实现并不像我们想像的那么简单,是不是?你以后用的时候就在注意了,其实上面的应该调用wcslen返回正确的结果,看来并不是那么回事了.

         上面代码改成这样,第三个就能得到正确的结果了:

         swprintf(strTemp,L"%s",L"ngangche结果");

       int nLen = wcslen(strTemp); //nLen10,是我们想要得到的结果.

         再看一下内存,就知道为什么:


我们可以看到从0x0012ff00可以看到每个字符占两个字符,这一下结果正确了,一个API的理解不正确就可能导致不可预料的结果!比如上面的这个例子,我想可能引起的问题很多,因为涉及的字符的长度,很容易出问题的,看来写程序要更加细心的呀!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值