C++字符串完全指引之一 —— Win32 字符编码
- 格式:docx
- 大小:38.39 KB
- 文档页数:10
win32编程基础知识 尽管Windows应⽤程序千变万化,令⼈眼花缭乱,但,消息机制和窗⼝过程却始终它们的基础,掌握了这两项技术,也就相当于把握住了问题的关键。
如果你以前是C程序员或是MFC的忠实⽤户,只要你学习过C语⾔的语法,⾃⼰亲⼿编过⼀些简短的C程序,理解以下的Win32编程基础也不是⼀件困难的事。
⼀个最简单的Win32程序 在以前的C语⾔编程中,⼀个最简单的程序可以只有两⾏。
void main(void){ printf "Hello World!"; } ⽽要实现同样功能的Windows程序却最少也要写⼏⼗⾏,这并不是说明Windows应⽤程序效率低下,难于掌握,只是说明程序在Windows环境下有更丰富的内涵。
Windows程序的效率其实不低,在所有的Windows应⽤程序中,都有⼀个程序初始化的过程,这得⽤上⼏⼗条语句,这段初始化的代码对于任何Windows应⽤程序⽽⾔,都是⼤同⼩异的。
下⾯以⼀个实现最简单功能的程序EasyWin为例,说明Windows程序的基本框架。
打开Visual C++ 6.0。
选择File菜单的New,在出现的对话框中,选择Projects栏⽬(新建⼯程),并点取其下的Win32 Application项,表⽰使⽤Win32环境创建应⽤程序。
先在Locatin(路径)中填⼊“c:\”,然后在Project Name(项⽬名称)中填⼊“EasyWin”,其它按照缺省设置)。
单击OK按钮。
再次选择File菜单的New,在出现的对话框中,选择Files栏⽬(新建⽂件),并点取其下的C++ Source File项,表⽰新建⼀个C++源⽂件。
在右边的File栏中输⼊“EasyWin”,最后确定让Add to project检查框打上勾)。
单击OK按钮。
在EasyWin.cpp⽂件中输⼊以下源程序代码。
//*******************************************************************// ⼯程:easywin// ⽂件:easywin.cpp// 内容:⼀个基本的Win32程序//*******************************************************************#include <windows.h>#include <windowsx.h>//函数声明BOOL InitWindow( HINSTANCE hInstance, int nCmdShow );LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );//*******************************************************************//函数:WinMain()//功能:Win32应⽤程序⼊⼝函数。
c语言32位无符号整型转字符串(原创实用版)目录1.介绍 C 语言 32 位无符号整型转字符串的背景和需求2.解释 32 位无符号整型的范围和表示方法3.介绍将 32 位无符号整型转换为字符串的方法4.举例说明如何使用这些方法进行转换5.总结和未来发展正文C 语言是一种广泛使用的编程语言,其功能丰富,可以进行各种复杂的操作。
在 C 语言中,整数类型是非常重要的一种数据类型,它可以用来进行各种数学运算和逻辑操作。
然而,有时候我们需要将整数类型转换为字符串类型,以便更好地进行数据处理和显示。
本文将介绍如何将 32 位无符号整型转换为字符串。
32 位无符号整型是 C 语言中的一种整数类型,它可以表示 0 到4294967295 之间的整数。
由于它是无符号的,所以它可以表示正数和负数,而不会丢失数据。
这种类型的整数在计算机内部以 4 字节的形式存储,每个字节有 8 位,总共有 32 位。
要将 32 位无符号整型转换为字符串,可以使用 C 语言中的格式化输入和输出函数。
其中,最常用的函数是 sprintf 和 printf。
这两个函数的使用方法类似,只是 sprintf 函数是在一个字符串中格式化输出,而 printf 函数是直接输出到屏幕上。
下面是一个使用 sprintf 函数将 32 位无符号整型转换为字符串的例子:```c#include <stdio.h>int main(){unsigned int num = 4294967295;char str[10];sprintf(str, "%u", num);printf("%s", str);return 0;}```在这个例子中,我们首先定义了一个 32 位无符号整型变量 num,并将其赋值为 4294967295。
然后,我们定义了一个字符数组 str,并用sprintf 函数将 num 转换为字符串,存储在 str 中。
Windows程序中的字符编码写这篇文章的起因是这么一个问题:我们在使用和安装Windows程序时,有时会看到以“2052”、“1033”这些数字为名的文件夹,这些数字似乎和字符集有关,但它们究竟是什么意思呢?研究这个问题的同时,又会遇到其它问题。
我们会谈到Windows的内部架构、Win32 API的A/W函数、Locale、ANSI代码页、与字符编码有关的编译参数、MBCS和Unicode程序、资源和乱码等,一起经历这段琐碎细节为主,间或乐趣点缀的旅程。
0 Where is Win32 APIWindows 程序有用户态和核心态的说法。
在32位地址空间中,0x80000000以下属于用户态,0x80000000以上属于核心态。
所有硬件管理都在核心态。
用户态程序的不能直接使用核心态的任何代码。
所谓核心态其实只是CPU的一种保护模式。
在x86 CPU上,用户态处于ring 3,核心态处于ring 0。
从用户态进入核心态的最常用的方法是在寄存器eax填一个功能码,然后执行int 2e。
这有点像DOS时代的DOS和BIOS系统调用。
在NT架构中这种机制被称作system service。
在核心态提供system service的有两个家伙:ntoskrnl.exe和win32k.sys。
ntoskrnl.exe是Windows的大脑,它的上层被称为Executive,下层被称作Kernel。
Win32k.sys提供与显示有关的system service。
在用户态一侧,有一个重要的角色叫作ntdll.dll,大多数system service都是它调用的。
它封装这些system service,然后提供一个API接口。
这个接口被称作native API。
native API的用户是各个子系统(subsystem),包括Win32子系统、OS/2子系统、POSIX子系统。
各个子系统为Win32、OS2、POSIX程序提供了运行平台。
32个字符编码通常可以使用5位二进制数来表示。
这是因为,一个二进制位可以表示两种状态(0或1),所以n位二进制数可以表示的总数为2^n种状态。
要表示32个不同的字符,我们只需要找到最小的n使得2^n >= 32。
计算得知:
2^4 = 16
2^5 = 32
因此,至少需要5位二进制数才能表示32个字符。
这个原理适用于任何基于二进制的系统,包括计算机和单片机中的内存存储。
在实际应用中,比如在Windows操作系统中,有一种称为多字节字符集(MBCS)的编码方式,它包含了一些一个字节长的字符,以及一些大于一个字节长度的字符。
对于ASCII码以外的字符,这种编码通常是用两个字节来表示的。
然而,这并不意味着每个字符都恰好占用5位二进制,因为计算机内部实际上是以字节(8位二进制)为基本单位进行处理的。
编码标准:ASCII、GBK、Unicode(UTF8、UTF16、UTF32)
英⽂编码(单字节字符集,码值范围0~127):字节最⾼位是0
ASCII编码,⽤于英⽂字符。
中⽂编码(双字节字符集):⾸字节(8位)的最⾼位是1。
可依据⾸字节最⾼位来判断中英⽂。
GB2312,旧版,6763个汉字。
GBK,中⽂字符升级版,21000多个汉字。
国际编码:Unicode编码,各国语⾔字符
不同编码⽅式,值不同,如“中”的GBK编码:0xD6D0,Unicode编码:0x4E2D
Unicode编码的3种实现⽅式:UTF8、UTF16、UTF32。
UTF8变长编码,智能分配1-4个字节。
UTF16定长编码,2个字节。
UTF32定长编码,4个字节。
UTF16编码,中英⽂字符都占2个字节。
其定义的类型称为宽字符类型wchar_t,使⽤⽅式如下
wchar_t d[] = L"中国"; //宽字符类型
wcout.imbue(locale("chs"));//Windows系统,语⾔设置为简体中⽂。
Unicode转GBK
wcout << d; //宽字符输出,中国。
C++字符串完全指引之一—— Win32 字符编码原著:Michael Dunn翻译:Chengjie Sun原文出处:CodeProjec t:The Complete Gu ide to C++ Strings, Part I引言毫无疑问,我们都看到过像TCHAR, std::string, BSTR 等各种各样的字符串类型,还有那些以_tcs 开头的奇怪的宏。
你也许正在盯着显示器发愁。
本指引将总结引进各种字符类型的目的,展示一些简单的用法,并告诉您在必要时,如何实现各种字符串类型之间的转换。
在第一部分,我们将介绍3种字符编码类型。
了解各种编码模式的工作方式是很重要的事情。
即使你已经知道一个字符串是一个字符数组,你也应该阅读本部分。
一旦你了解了这些,你将对各种字符串类型之间的关系有一个清楚地了解。
在第二部分,我们将单独讲述string类,怎样使用它及实现他们相互之间的转换。
字符基础-- ASCII, DBCS, Unicode所有的string 类都是以C-sty le字符串为基础的。
C-sty le 字符串是字符数组。
所以我们先介绍字符类型。
这里有3种编码模式对应3种字符类型。
第一种编码类型是单子节字符集(sing le-by te character set or SBCS)。
在这种编码模式下,所有的字符都只用一个字节表示。
ASCII是SBCS。
一个字节表示的0用来标志SBCS字符串的结束。
第二种编码模式是多字节字符集(mult i-by te character set or MBCS)。
一个MBCS编码包含一些一个字节长的字符,而另一些字符大于一个字节的长度。
用在W indows里的MBCS包含两种字符类型,单字节字符(sing le-by te characters)和双字节字符(double-by te characters)。
由于W indows里使用的多字节字符绝大部分是两个字节长,所以MBCS常被用DBCS代替。
C#基础知识:字符编码、编码转换⼀、 ASCII码我们知道,在计算机内部,所有的信息最终都表⽰为⼀个⼆进制的字符串。
每⼀个⼆进制位(bit)有0和1两种状态,因此⼋个⼆进制位就可以组合出256种状态,这被称为⼀个字节(byte)。
也就是说,⼀个字节⼀共可以⽤来表⽰256种不同的状态,每⼀个状态对应⼀个符号,就是256个符号,从00000000到11111111。
上个世纪60年代,美国制定了⼀套字符编码,对英语字符与⼆进制位之间的关系,做了统⼀规定。
这被称为ASCII码,⼀直沿⽤⾄今。
ASCII码⼀共规定了128个字符的编码,⽐如空格“SPACE”是32(⼆进制00100000),⼤写的字母A是65(⼆进制01000001)。
这128个符号(包括32个不能打印出来的控制符号),只占⽤了⼀个字节的后⾯7位,最前⾯的1位统⼀规定为0。
在C#中如果你想看看某个字母的ASCII码是多少,可以使⽤表⽰字符编码的类Encoding ,代码如下:string s = "a";byte[] ascii = Encoding.ASCII.GetBytes(s);我们通过调试器可以看到ascii中为97,也就是说a的ASCII码为97(1100001)⼆、⾮ASCII编码英语⽤128个符号编码就够了,但是⽤来表⽰其他语⾔,128个符号是不够的。
⽐如,在法语中,字母上⽅有注⾳符号,它就⽆法⽤ASCII码表⽰。
于是,⼀些欧洲国家就决定,利⽤字节中闲置的最⾼位编⼊新的符号。
⽐如,法语中的é的编码为130(⼆进制10000010)。
这样⼀来,这些欧洲国家使⽤的编码体系,可以表⽰最多256个符号。
但是,这⾥⼜出现了新的问题。
不同的国家有不同的字母,因此,哪怕它们都使⽤256个符号的编码⽅式,代表的字母却不⼀样。
⽐如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel ,在俄语编码中⼜会代表另⼀个符号。
32个字符编码
(最新版)
目录
1.32 个字符编码的概述
2.32 个字符编码的来源和应用
3.32 个字符编码的优缺点
4.我国在 32 个字符编码方面的发展
正文
32 个字符编码是一种计算机中用于表示字符的编码方式,它可以表示大小写字母、数字和一些特殊符号,是计算机信息处理中常用的编码方式之一。
32 个字符编码最早来源于 ASCII 编码,ASCII 编码是一种将字符与数字对应起来的编码方式,其中包括了大写字母、小写字母、数字和一些特殊符号。
随着计算机技术的发展,32 个字符编码逐渐被广泛应用,比如在网络传输、数据存储和程序设计等方面都有 32 个字符编码的影子。
32 个字符编码的优点在于其简单易懂,能够表示大部分常见的字符,而且兼容性好,能够被大部分计算机系统识别。
但是,32 个字符编码也有其缺点,那就是字符数量有限,不能表示所有的字符,比如中文字符就无法用 32 个字符编码来表示。
我国在 32 个字符编码方面的发展也取得了一定的成就。
我国自主研发的 GBK 编码,可以表示更多的字符,包括中文字符和其他一些特殊字符。
GBK 编码的推出,为我国的计算机信息处理提供了更大的便利。
第1页共1页。
Windows程序员必须知道的字符编码和字符集1. 字符编码 (Character encoding)在存储和传递⽂本过程中,为了使得所有电脑都能够正确的识别出⽂本内容,需要有⼀个统⼀的规则。
2. 字符集 (Character Set) )⼀般情况,⼀种编码⽅式对应⼀种字符集。
如 ASCII,对应 ASCII 字符集。
GBK 编码⽅式对应 GBK 字符集。
但是也有⼀种编码⽅式,多种字符集的,Unicode 字符集有多种编码⽅式,如 utf-8,utf-16 等。
3. ASCIIASCII(American Standard Code for Information Interchange,美国信息交换标准代码):使⽤ 7 个 Bit 表⽰,共 128 个字符,刚好占⽤了⼀个字节中的后 7 位,共包括33 个控制字符和 95 个可显⽰字符。
. 4. ANSIANSI (⼀种字符编码,此处不是表⽰美国国家标准学会的意思):ANSI 是为了让计算机⽀持更多的语⾔,⽽在 ASCII 的*础上的⼀种扩展字符编码。
在不同语⾔操作上,ANSI 都表⽰当前计算机默认的编码⽅式。
如在简体 Windows 操作下,ANSI 编码代表 GBK 编码;在繁体中⽂操作下,ANSI 编码代表 Big5 编码;在⽇⽂ Windows 操作系统中,ANSI 编码代表 Shift_JIS 编码;在英⽂操作系统下,ANSI 就是ASCII 编码。
. 5. MBCSMBCS(Multi-Byte Character Set),早在 1980 年,中国就提出了使⽤ GB2312 编码⽅式来描述汉字。
后来其他东亚国家也利⽤这种⽅式扩展 ASCII 编码字符集。
台湾地区 5 ⼤企业推出的繁体 Big5 码,⾹港新加坡等后来也利⽤。
⽇本韩国也相应推出了⾃⼰的编码⽅式。
其实在这⾥,BIG5 既是编码⽅式,也是字符集。
. 6. GB2312(Guo Biao 2312) )⽤双字节表⽰汉字,但是为了完全兼容 ASCII。
Windows字符串类型C++主要使用的是C-Style字符串,而M$在Windows中又增加了很多C-Style字符串的变体。
这个一多嘛,就容易乱~所谓字符串,就是由字符组合而成,所以我们先来将将字符类型。
首先,存在两种最基本的字符类型:char和wchar_t。
char大家都很熟悉了,我就跳过。
至于wchar_t,是应用于UNICODE的宽字符,即一个字符2Bytes,16Bits。
事实上,Windows 中利用typedef unsigned short wchar_t定义wchar_t然后为了书写方便(MS我也没觉得有多大差别),M$又把那两个基本字符类型重新的给他typedef了一遍,即:typedef char CHARtypedef wchar_t WCHAR为了使得兼容性更加,M$又定义了TCHAR数据类型:#ifdef UNIOCDEtypedef WCHAR TCHAR#elsetypedef CHAR TCHAR#endif这样,你不用关心是要使用ANSI字符串还是Unicode,编译器会自动根据你的OS来选择。
然后,M$又利用上面的几种基本数据类型,定义了一些字符串指针类型。
LPSTR和LPCSTR:LPSTR是指向以0结尾的ANSI字符串的指针,后者是const指针typedef CHAR* LPSTRtypedef const CHAR* LPCSTRLPWSTR和LPCWSTR:LPWSTR是指向以0结尾的UNICODE字符串的指针,后者是const 指针typedef WCHAR* LPWSTRtypedef const WCHAR* LPCWSTR同样,为了摆脱对ANSI还是UNICODE的选择麻烦,M$也增加了LPTSTR和LPCTSTR两个字符串指针类型。
他们被如下定义:typedef TCHAR* LPTSTR#ifdef UNICODEtypedef LPWSTR LPTSTR#elsetypedef LPSTR LPTSTR#endif/////////////////////////////////////typedef const TCHAR* LPCTSTR#ifdef UNICODEtypedef LPCWSTR LPCTSTR#elsetypedef LPCSTR LPCTSTR#endifps:你会在某些地方看到存在PSTR/PWSTR/PTSTR等等,与上面的只却一个L的字符串指针类型。
C++字符串完全指引之一—— Win32 字符编码原著:Michael Dunn引言毫无疑问,我们都看到过像TCHAR, std::string, BSTR 等各种各样的字符串类型,还有那些以_tcs 开头的奇怪的宏。
你也许正在盯着显示器发愁。
本指引将总结引进各种字符类型的目的,展示一些简单的用法,并告诉您在必要时,如何实现各种字符串类型之间的转换。
在第一部分,我们将介绍3种字符编码类型。
了解各种编码模式的工作方式是很重要的事情。
即使你已经知道一个字符串是一个字符数组,你也应该阅读本部分。
一旦你了解了这些,你将对各种字符串类型之间的关系有一个清楚地了解。
在第二部分,我们将单独讲述string类,怎样使用它及实现他们相互之间的转换。
字符基础-- ASCII, DBCS, Unicode所有的string 类都是以C-style字符串为基础的。
C-style 字符串是字符数组。
所以我们先介绍字符类型。
这里有3种编码模式对应3种字符类型。
第一种编码类型是单子节字符集(single-byte character set or SBCS)。
在这种编码模式下,所有的字符都只用一个字节表示。
ASCII是SBCS。
一个字节表示的0用来标志SBCS字符串的结束。
第二种编码模式是多字节字符集(multi-byte character set or MBCS)。
一个MBCS编码包含一些一个字节长的字符,而另一些字符大于一个字节的长度。
用在Windows里的MBCS包含两种字符类型,单字节字符(single-byte characters)和双字节字符(double-byte characters)。
由于Windows里使用的多字节字符绝大部分是两个字节长,所以MBCS常被用DBCS代替。
在DBCS编码模式中,一些特定的值被保留用来表明他们是双字节字符的一部分。
例如,在Shift-JIS编码中(一个常用的日文编码模式),0x81-0x9f之间和0xe0-oxfc之间的值表示"这是一个双字节字符,下一个子节是这个字符的一部分。
"这样的值被称作"leading bytes",他们都大于0x7f。
跟随在一个leading byte子节后面的字节被称作"trail byte"。
在DBCS中,trail byte可以是任意非0值。
像SBCS一样,DBCS字符串的结束标志也是一个单字节表示的0。
第三种编码模式是Unicode。
Unicode是一种所有的字符都使用两个字节编码的编码模式。
Unicode字符有时也被称作宽字符,因为它比单子节字符宽(使用了更多的存储空间)。
注意,Unicode不能被看作MBCS。
MBCS的独特之处在于它的字符使用不同长度的字节编码。
Unicode字符串使用两个字节表示的0作为它的结束标志。
单字节字符包含拉丁文字母表,accented characters及ASCII标准和DOS操作系统定义的图形字符。
双字节字符被用来表示东亚及中东的语言。
Unicode 被用在COM及Windows NT操作系统内部。
你一定已经很熟悉单字节字符。
当你使用char时,你处理的是单字节字符。
双字节字符也用char类型来进行操作(这是我们将会看到的关于双子节字符的很多奇怪的地方之一)。
Unicode字符用wchar_t来表示。
Unicode字符和字符串常量用前缀L来表示。
例如:wchar_t wch = L''1''; // 2 bytes, 0x0031wchar_t* wsz = L"Hello"; // 12 bytes, 6 wide characters字符在内存中是怎样存储的单字节字符串:每个字符占一个字节按顺序依次存储,最后以单字节表示的0结束。
例如。
"Bob"的存贮形式如下:Unicode的存储形式,L"Bob"使用两个字节表示的0来做结束标志。
一眼看上去,DBCS 字符串很像SBCS 字符串,但是我们一会儿将看到DBCS 字符串的微妙之处,它使得使用字符串操作函数和永字符指针遍历一个字符串时会产生预料之外的结果。
字符串" " ("nihongo")在内存中的存储形式如下(LB和TB分别用来表示leading byte 和trail byte)LB TB LB TB LB TB值得注意的是,"ni"的值不能被解释成WORD型值0xfa93,而应该看作两个值93和fa以这种顺序被作为"ni"的编码。
使用字符串处理函数我们都已经见过C语言中的字符串函数,strcpy(), sprintf(), atoll()等。
这些字符串只应该用来处理单字节字符字符串。
标准库也提供了仅适用于Unicode 类型字符串的函数,比如wcscpy(), swprintf(), wtol()等。
微软还在它的CRT(C runtime library)中增加了操作DBCS字符串的版本。
Str***()函数都有对应名字的DBCS版本_mbs***()。
如果你料到可能会遇到DBCS字符串(如果你的软件会被安装在使用DBCS编码的国家,如中国,日本等,你就可能会),你应该使用_mbs***()函数,因为他们也可以处理SBCS字符串。
(一个DBCS字符串也可能含有单字节字符,这就是为什么_mbs***()函数也能处理SBCS字符串的原因)让我们来看一个典型的字符串来阐明为什么需要不同版本的字符串处理函数。
我们还是使用前面的Unicode字符串L"Bob":因为x86CPU是little-endian,值0x0042在内存中的存储形式是42 00。
你能看出如果这个字符串被传给strlen()函数会出现什么问题吗?它将先看到第一个字节42,然后是00,而00是字符串结束的标志,于是strlen()将会返回1。
如果把"Bob"传给wcslen(),将会得出更坏的结果。
wcslen()将会先看到0x6f42,然后是0x0062,然后一直读到你的缓冲区的末尾,直到发现00 00结束标志或者引起了GPF。
到目前为止,我们已经讨论了str***()和wcs***()的用法及它们之间的区别。
Str***()和_mbs**()之间的有区别区别呢?明白他们之间的区别,对于采用正确的方法来遍历DBCS字符串是很重要的。
下面,我们将先介绍字符串的遍历,然后回到str***()与_mbs***()之间的区别这个问题上来。
正确的遍历和索引字符串因为我们中大多数人都是用着SBCS字符串成长的,所以我们在遍历字符串时,常常使用指针的++-和-操作。
我们也使用数组下标的表示形式来操作字符串中的字符。
这两种方式是用于SBCS和Unicode字符串,因为它们中的字符有着相同的宽度,编译器能正确的返回我们需要的字符。
然而,当碰到DBCS字符串时,我们必须抛弃这些习惯。
这里有使用指针遍历DBCS字符串时的两条规则。
违背了这两条规则,你的程序就会存在DBCS有关的bugs。
∙1.在前向遍历时,不要使用++操作,除非你每次都检查lead byte;∙2.永远不要使用-操作进行后向遍历。
我们先来阐述规则2,因为找到一个违背它的真实的实例代码是很容易的。
假设你有一个程序在你自己的目录里保存了一个设置文件,你把安装目录保存在注册表中。
在运行时,你从注册表中读取安装目录,然后合成配置文件名,接着读取该文件。
假设,你的安装目录是C:\Program Files\MyCoolApp,那么你合成的文件名应该是C:\Program Files\MyCoolApp\config.bin。
当你进行测试时,你发现程序运行正常。
现在,想象你合成文件名的代码可能是这样的:bool GetConfigFileName ( char* pszName, size_t nBuffSize ){char szConfigFilename[MAX_PATH];// Read install dir from registry... we''ll assume it succeeds.// Add on a backslash if it wasn''t present in the registry value.// First, get a pointer to the terminating zero.char* pLastChar = strchr ( szConfigFilename, ''\0'' );// Now move it back one character.pLastChar--;if ( *pLastChar != ''\\'' )strcat ( szConfigFilename, "\\" );// Add on the name of the config file.strcat ( szConfigFilename, "config.bin" );// If the caller''s buffer is big enough, return the filename.if ( strlen ( szConfigFilename ) >= nBuffSize )return false;else{strcpy ( pszName, szConfigFilename );return true;}}这是一段很健壮的代码,然而在遇到DBCS 字符时它将会出错。
让我们来看看为什么。
假设一个日本用户使用了你的程序,把它安装在C:\。
下面是这个名字在内存中的存储形式:TB TB TB当使用GetConfigFileName() 检查尾部的''\\''时,它寻找安装目录名中最后的非0字节,看它是等于''\\''的,所以没有重新增加一个''\\''。
结果是代码返回了错误的文件名。
哪里出错了呢?看看上面两个被用蓝色高量显示的字节。
斜杠''\\''的值是0x5c。
'' ''的值是83 5c。
上面的代码错误的读取了一个trail byte,把它当作了一个字符。
正确的后向遍历方法是使用能够识别DBCS字符的函数,使指针移动正确的字节数。