字符集之 代码书写和底层探索

遭遇问题:

1.工程配置为多字节字符集时,工程中代码书写用宽字节字符类型和函数的情况是基本无实际用途的,因为我用了MFC等三方库,界面显示到底是由它负责的,在机子配置是非本地语言的情况下界面显示还是乱码,原因估计是三方库这部分还是处理成了ANSI的情况。

2.当主工程和动态链接库工程采用不同的字符集配置时,出现了启动对话框崩溃现象,尽管dll接口中没有出现使用字符串对象的现象。我想原因还是出在了使用MFC等三方库的问题上,崩溃的地方是在MFC资源句柄的访问语句,而且资源切换代码写的绝对没有问题。很难想象MFC类库如何应对同一进程执行中两模块不同配置的情况。

3.不要以为能编译通过就没有乱码问题,比如MFC::CString("古月")不加_T宏在UNICODE配置下能编过,但用此字符串对象创建的控件标题在非本地语言机子上显示乱码。能编过是因为它的构造函数有此接口,可能是在内部转化的。

 

代码书写注意事项:

1.用字符串常量构造字符串对象时,std::wstring时用宏L;构造CString和别的随配置可变字宽类型对象时用宏_T;

2.用系统函数时要选用可随系统配置变化的API如:::GetDirect(),并传入可变字宽的字符串对象如LPCTSTR,
   不提昌用::GetDirectA()或::GetDirectW()这样被定死的;

3.当需要外来参数向本地代码参数传值或相反情况时,如果其中一个参数是可随配置变化的,另一个是定死的,此时
    建议用宏把代码区分开:#ifdef _UNICODE
m_img = new Gdiplus::Image(szFilename,FALSE);
#else
m_img = new Gdiplus::Image(A2W(szFilename), FALSE);
#endif

4.构造CString类对象时,要用_T,不然虽能编过(内部转换),CString("古月方")即使以UNICODE编译的在非本地语言机子上显示还是乱码。
   我是比较喜爱CString的高效易用和灵活性的。它内部的引用计数机制和随配置字宽可变性是很好的。

5.替换常用的正则表达式:
_T\({"[^"]*"}\)
L\1

MessageBox\(L{"[^"]*"}
MessageBox(_T(\1)

MessageBox\({[^,]*},L{"[^"]*"}
MessageBox(\1,_T(\2)

MessageBox\({[^,]*}, {[^,]*}, L{"[^"]*"}
MessageBox(\1, \2, _T(\3)


C 语言原本是在英文环境中设计的,主要的字符集是7 位的ASCII 码。从此开始,8 位的byte(字节)变成最常见的字符编码单位,但是国际化软件必须能够表示不同的字符,ISO C 可以标准化两种表示大型字符集的方法:宽字符(wide character,该字符集内每个字符使用相同的位长)以及多字节字符(multibyte character,每个字符可以是一到多个字节不等,而某个字节序列的字符值由字符串或流(stream)所在的环境背景决定)。
注意:虽然C现在提供抽象机制,可以处理和转换不同种类的编码集合,但语言本身并没有定义或指定任何编码集合,或任何字符集(除基本源代码字符集和基本运行字符集外)。换句话说,这部分是由个别的实现版本指定如何编码宽字符,以及要支持什么类型的多字节字符编码机制。
自从1994 年的增补之后,C 不只提供char类型,还提供wchar_t类型(宽字符),此类型定义在stddef.h 头文件中。wchar_t 类型足以表示某个实现版本扩展字符集的任何元素。虽然C 标准没有支持Unicode 字符集,许多实现版本使用Unicode 转换格式UTF-16 和UTF-32来处理宽字符。
C 提供了一些标准函数,可以将多字节字符转换为wchar_t,或将宽字符转换为多字节字符。比方说,如果C 编译器使用Unicode 标准的UTF-16 和UTF-8,下面函数就可以获得字符的多字节表示方式(注:wctomb = WideCharToMultiByte())。


C++的中英文字符串默示(string,wstring),字符串类的模板原型是basic_string
string完全可以存储中文(有效编码只有""\0""=0,其他字符均不为0),然则在显示、字符操纵等方面是无法包管正确的!
前者string是常用类型,可以看作char[],其实这恰是与string定义中的_Elem=char相一致。而wstring,应用的是wchar_t类型,这是宽字符,用于满足非ASCII字符的请求,例如Unicode编码,中文,日文,韩文什么的。对于wchar_t类型,实际上C++中都用与char函数相对应的wchar_t的函数,因为他们都是从同一个模板类似于上方的体式格式定义的。是以也有wcout,wcin,werr等函数。实际上string也可以应用中文,然则它将一个汉字写在2个char中,但有些函数操作出错。而若是将一个汉字看作一个单位wchar_t的话,那么在wstring中就只占用一个单位,其它的非英文文字和编码也是如此。如许才真正的满足字符串操纵的请求,尤其是国际化等工作。


(CSDN资料)VS2010中字符集配置:定义是否应该设置 _UNICODE 或 _MBCS。在适当的地方还影响链接器入口点。
可以通过用字母 L 作为字符的前缀将任何 ASCII 字符表示为宽字符形式。例如,L'\0' 是宽(16 位)NULL 字符。同样,可以通过用字母 L 作为 ASCII 字符串的前缀 (L"Hello") 将任何 ASCII 字符串表示为宽字符字符串形式。
C 运行时库有两类内部代码页:区域设置和多字节。在程序执行期间可以更改当前代码页(有关 setlocale 和 _setmbcp 函数的信息,请参见文档)。而且,运行时库可以获取并使用操作系统代码页的值。在 Windows 2000 中,操作系统代码页是“系统默认 ANSI”代码页。此代码页在程序的执行期间保持不变。


内码是指操作系统内部的字符编码。早期操作系统的内码是与语言相关的使用7位的ASCII编码。为了处理汉字,程序员设计了用于简体中文的Windows内码GBK。目前Windows的内核已经支持Unicode字符集,然后用代码页适应各种语言,“内码”的概念就比较模糊了。微软一般将缺省代码页指定的编码说成是内码,即缺省用什么编码来解释字符。例如Windows的记事本打开了一个文本文件,里面的内容是字节流:BA、BA、D7、D6。Windows应该去怎么解释它呢?是按照Unicode编码解释、还是按照GBK解释?
答案是Windows按照当前的缺省代码页去解释文本文件里的字节流。缺省代码页可以通过控制面板的区域选项设置。记事本的另存为中有一项ANSI,其实就是按照缺省代码页的编码方法保存。
Windows的内码是Unicode,它在技术上可以同时支持多个代码页。只要文件能说明自己使用什么编码,用户又安装了对应的代码页,Windows就能正确显示。Unicode也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。

Unicode最早的编码想法,就是把每一个码点(code point)都存储在两个字节中,这也就导致了大多数人的误解,于是非常聪明的UTF-8的概念被引入了,用来存储字符串所对应的Unicode的码点。
UTF-8就是以8位为单元对UCS(Unicode字符集)进行编码。
读者可以用记事本测试一下我们的编码是否正确。需要注意,UltraEdit在打开utf-8编码的文本文件时会自动转换为UTF-16,可能产生混淆。你可以在设置中关掉这个选项。更好的工具是Hex Workshop。

 

C语言中,字符(character)这个术语具有两个层次上的含义:书写源程序的字符和程序处理的字符。
例如,printf("你好,C!\n");  之内的“你好\n”就属于程序要处理的字符。
从某种意义上来说,编辑/编译器是一种接受字符输入,输出可执行文件的软件,由它产生可执行文件经过加载成为内存中的程序,这个程序通常也不可避免地要处理字符。
编辑/编译器所要处理的字符就是书写C语言源程序所用的字符,这种字符的集合叫源字符集(sourcecharacter set)。而应用程序要处理的字符所构成的集合叫执行字符集(execution character set)。这两者又不同于编码时的字符集及其配置的概念。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值