字符编码方式

来源:互联网 发布:暴雪cg 知乎 编辑:程序博客网 时间:2024/06/04 17:55

在学习命令行参数的时候发现了一个问题,argv[]中的字符串无法正确输出,每次都只能输出第一个字符。

在马大神的尝试下,更改了入口函数,发现问题解决了。

原函数如下:

int _tmain(int argc, _TCHAR* argv[])

修改后如下:

int main(int argc, char* argv[])

首先对函数的第二个参数进行说明:

Windows为了消除各编译器的差别,重新定义了一些数据类型,CHAR,TCHAR,LPSTR,LPCSTR几个类型都是这样的。 

char是C语言标准数据类型,字符型,至于由几个字节组成通常由编译器决定,一般一个字节。还有个WCHAR为Unicode字符,即不论中英文,每个字有两个字节组成。如果当前编译方式为ANSI(默认)方式,TCHAR等价于CHAR,如果为Unicode方式,TCHAR等价于WCHAR。这样对应的就有了两套字符串字符串处理函数,比如:strlen和wcslen,分别用于处理两种字符串。

LPSTR:32bit指针指向一个字符串,每个字符占1字节

LPCSTR:32-bit指针指向一个字符串,每个字符占1字节

LPCTSTR:32-bit指针指向一个字符串,每字符可能占1字节或2字节,取决于Unicode是否定义

LPTSTR:32-bit指针每字符可能占1字节或2字节,取决于Unicode是否定义


在VS2010中,项目默认采用的字符集为Unicode,所以入口函数的_TCHAR为两字节字符,也就是WCHAR。

所以问题在于printf或者cout都是对char类型的输出,所以遇到了WCHAR也就只能输出第一个字符。

而对于WCHAR也有其自有的wcout,而printf则可以改成_tprintf,并且""内的字符串需要用_T()括起来才可以。_T()这一存在其实也和编译方式有关如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把字符串以UNICODE方式保存。在这里,提一下两种编译方式的包裹,常规的ANSI编码(使用""包裹)和Unicode编码(使用L""包裹)。而_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。

同理,在不同名称的入口函数也是这个原理,main和_tmain:

_tmain()是微软操作系统(windows)提供的对unicode字符集和ANSI字符集进行自动转换用的程序入口点函数。

当你程序当前的字符集为unicode时,int _tmain(int argc, TCHAR *argv[])会被翻译成int wmain(int argc, wchar_t *argv[])

当你程序当前的字符集为ANSI时,int _tmain(int argc, TCHAR *argv[])会被翻译成int main(int argc, char *argv[])

所以,我们可以这样说,_T的出现是为了统一两个不同的编码方式ANSI和Unicode。


最后,来谈一下Unicode。

Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。

大概来说,Unicode 编码系统可分为编码方式和实现方式两个层次。

Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。在Unicode中:汉字“字”对应的数字是23383。

在Unicode中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。这其中的UTF-8、UTF-16、UTF-32实现方式没有细究,只是大概看了UTF-8貌似是利用哈夫曼编码进行的。

原创粉丝点击