vb string类型变量在内存的表示?解决方法
vb string类型变量在内存的表示?
vb string类型变量在内存的表示?
1
一般来说,vb字符串都使用UNICODE表示,不管汉字还是英文字符都应该是两个字节。
eg.一个字符串在内存中,占的字节数应该是 总内存=字符个数*2字节
2
内存分布应该是汉字两个字节,英文一个字节
eg.
dim string*10
“我123456789”
内存分布应该是:
内存单元 0 1 2 3 4 5 6 7 8 9
-50 -17 0 50 0 51 0 52 0 53
? ? 2 3 4 5
实际上内存分布是以下样式:
-50 -17 50 51 52 53 54 55 56 57
以字符显示:? ? 2 3 4 5 6 7 8 9
为什么会这样呢?
------解决方案--------------------
LZ:参考下MSDN的说明:
ANSI、DBCS 和 Unicode 的定义
Visual Basic 使用 Unicode 存储和操作字符串。Unicode 是一种用两个字节表示一个字符的字符集。另外一些程序,如 Windows 95 API,使用 ANSI (American National Standards Institute) 或 DBCS 存储和操作字符串。当从 Visual Basic 移出字符串时,会遇到 Unicode 和 ANSI/DBCS 之间的差别。下表列出了不同环境下 ANSI、DBCS 和 Unicode 字符集。
环境 使用的字符集
Visual Basic Unicode
32-bit 对象库 Unicode
16-bit 对象库 ANSI 和 DBCS
Windows NT API Unicode
Automation in Windows NT Unicode
Windows 95 API ANSI 和 DBCS
Automation in Windows 95 Unicode
ANSI
ANSI 是个人计算机使用得最普遍的字符集。由于 ANSI 标准使用单一字节表示每个字符,因此最多只能有 256 个字符和标点符号代码。虽然对英语来说已经足够了,但不能完全支持其它语言。
DBCS发行在亚洲大部分地区的 Microsoft Windows 系统使用 DBCS。它支持很多不同的东亚语言字母,如汉语、日语和朝鲜语。DBCS 使用数字 0–128 表示 ASCII 字符集。其它大于 128 的数字作为前导字节字符,它并不是真正的字符,只是简单的表明下一个字符属于非拉丁字符集。在 DBCS 中,ASCII 字符的长度是一个字节,而日语、朝鲜语和其它东亚字符的长度是 2 个字节。
Unicode
Unicode 是用两个字节表示每个字符的字符编码方案。国际标准组织 (ISO) 几乎为每种语言的每个字符和符号在 0 到 65,535 (216 – 1) 范围内定义了一个数字(再加上为将来发展保留的一些空余空间)。在所有 32 位版本的 Windows 中,部件对象模型 (COM) 都使用 Unicode,它是 OLE 和 ActiveX 技术的基础。Windows NT 全部支持 Unicode。虽然 Unicode 和 DBCS 都是双字节字符,但它们的编码方案完全不同。
字符代码示例
图 16.4 显示了每一个字符集中的一个字符代码示例。注意双字节字符每一个字节的代码不同。
图 16.4 ANSI、Unicode 和 DBCS 中 "A" 的字符代码
------解决方案--------------------
2F 、3F 的说法,‘理论上’基本正确,但“例举的事实”肯定是错误的。
废话少说,事实为证:
vb string类型变量在内存的表示?
1
一般来说,vb字符串都使用UNICODE表示,不管汉字还是英文字符都应该是两个字节。
eg.一个字符串在内存中,占的字节数应该是 总内存=字符个数*2字节
2
内存分布应该是汉字两个字节,英文一个字节
eg.
dim string*10
“我123456789”
内存分布应该是:
内存单元 0 1 2 3 4 5 6 7 8 9
-50 -17 0 50 0 51 0 52 0 53
? ? 2 3 4 5
实际上内存分布是以下样式:
-50 -17 50 51 52 53 54 55 56 57
以字符显示:? ? 2 3 4 5 6 7 8 9
为什么会这样呢?
------解决方案--------------------
LZ:参考下MSDN的说明:
ANSI、DBCS 和 Unicode 的定义
Visual Basic 使用 Unicode 存储和操作字符串。Unicode 是一种用两个字节表示一个字符的字符集。另外一些程序,如 Windows 95 API,使用 ANSI (American National Standards Institute) 或 DBCS 存储和操作字符串。当从 Visual Basic 移出字符串时,会遇到 Unicode 和 ANSI/DBCS 之间的差别。下表列出了不同环境下 ANSI、DBCS 和 Unicode 字符集。
环境 使用的字符集
Visual Basic Unicode
32-bit 对象库 Unicode
16-bit 对象库 ANSI 和 DBCS
Windows NT API Unicode
Automation in Windows NT Unicode
Windows 95 API ANSI 和 DBCS
Automation in Windows 95 Unicode
ANSI
ANSI 是个人计算机使用得最普遍的字符集。由于 ANSI 标准使用单一字节表示每个字符,因此最多只能有 256 个字符和标点符号代码。虽然对英语来说已经足够了,但不能完全支持其它语言。
DBCS发行在亚洲大部分地区的 Microsoft Windows 系统使用 DBCS。它支持很多不同的东亚语言字母,如汉语、日语和朝鲜语。DBCS 使用数字 0–128 表示 ASCII 字符集。其它大于 128 的数字作为前导字节字符,它并不是真正的字符,只是简单的表明下一个字符属于非拉丁字符集。在 DBCS 中,ASCII 字符的长度是一个字节,而日语、朝鲜语和其它东亚字符的长度是 2 个字节。
Unicode
Unicode 是用两个字节表示每个字符的字符编码方案。国际标准组织 (ISO) 几乎为每种语言的每个字符和符号在 0 到 65,535 (216 – 1) 范围内定义了一个数字(再加上为将来发展保留的一些空余空间)。在所有 32 位版本的 Windows 中,部件对象模型 (COM) 都使用 Unicode,它是 OLE 和 ActiveX 技术的基础。Windows NT 全部支持 Unicode。虽然 Unicode 和 DBCS 都是双字节字符,但它们的编码方案完全不同。
字符代码示例
图 16.4 显示了每一个字符集中的一个字符代码示例。注意双字节字符每一个字节的代码不同。
图 16.4 ANSI、Unicode 和 DBCS 中 "A" 的字符代码
------解决方案--------------------
2F 、3F 的说法,‘理论上’基本正确,但“例举的事实”肯定是错误的。
废话少说,事实为证:
- VB code
Option Explicit Private Declare Sub GetMem1 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Byte) Private Sub Command1_Click() Dim strTest$, i&, k&, bytRet As Byte strTest = "Abc中文12345" k = VarPtr(strTest) Debug.Print "变量地址:", Hex$(k) Debug.Print "该内存数据:", For i = k To k + 3 GetMem1 i, bytRet Debug.Print Right$("0" & Hex$(bytRet), 2); " "; Next: Debug.Print k = StrPtr(strTest) Debug.Print "串数据地址:", Right$("00000000" & Hex$(k), 8) Debug.Print "字符串长度:", "&H"; Hex$(Len(strTest)); "字符"; " &H"; Hex$(LenB(strTest)); "字节" For i = k - 4 To k + Len(strTest) * 2 + 1 GetMem1 i, bytRet Debug.Print Hex$(i); ":", Right$("0" & Hex$(bytRet), 2) Next End Sub ' **** 某次的运行结果 **** '变量地址: 12F3A0 '该内存数据: 1C 06 1D 00 '串数据地址: 001D061C '字符串长度: &HA字符 &H14字节 '1D0618: 14 '1D0619: 00 '1D061A: 00 '1D061B: 00 '1D061C: 41 '1D061D: 00 '1D061E: 62 '1D061F: 00 '1D0620: 63 '1D0621: 00 '1D0622: 2D '1D0623: 4E '1D0624: 87 '1D0625: 65 '1D0626: 31 '1D0627: 00 '1D0628: 32 '1D0629: 00 '1D062A: 33 '1D062B: 00 '1D062C: 34 '1D062D: 00 '1D062E: 35 '1D062F: 00 '1D0630: 00 '1D0631: 00