在C言语中,我们运用char来界说字符,占用一个字节,最多只能表现128个字符,也就是ASCII码中的字符。盘算机来源于美国,char 可以表现一切的英文字符,在以英语为母语的国度完整没有成绩。
然则世界上存在许多分歧的言语,例如汉语、汉语、日语等有不计其数个字符,需求用多个字节来表现,称之为宽字符(Wide Character)。Unicode 是宽字符编码的一种,曾经被古代盘算机指定为默许的编码方法,Windows 2000今后的操作零碎,包含Windows 2000、XP、Vista、Win7、Win8、Win10、Windows Phone、Windows Server 等(它们统称为 Windows NT)都从底层支撑Unicode,存取效力比 char 要高。
更多内容请检查:ASCII编码与Unicode编码
C言语中的宽字符
在C言语中,运用wchar.h头文件中的wchar_t来界说宽字符,例如:
wchar_t ch = 'A';
wchar_t 被界说为typedef unsigned short wchar_t,和一个无符号整型一样,占用两个字节。
假如界说宽字符串,需求加前缀L,例如:
wchar_t *str = L"C言语中文网";
L是必需要加的,而且与字符串之间不克不及有空格,只要如许编译器才晓得每一个字符占用两个字节。
宽字符示例:
#include <stdio.h> #include <wchar.h> int main(){ char ch = 'A'; wchar_t wch = 'A'; char str[] = "C言语中文网"; wchar_t wstr[] = L"C言语中文网"; printf("ch=%d, wch=%d, str=%d, wstr=%d\n", sizeof(ch), sizeof(wch), sizeof(str), sizeof(wstr)); return 0; }
运转后果:
ch=1, wch=2, str=12, wstr=14
wstr 之所以比 str 多两个字节是由于:字符 'C' 占用两个字节,字符串完毕标记 '\0' 也占用两个字节。
宽字符串的长度
盘算ASCII字符串长度运用 strlen 函数,盘算宽字符串长度运用 wcslen 函数:
#include <stdio.h> #include <wchar.h> #include <string.h> int main(){ char str[] = "C言语中文网"; wchar_t wstr[] = L"C言语中文网"; printf("strlen(str)=%d, wcslen(wstr)=%d\n", strlen(str), wcslen(wstr)); return 0; }
运转后果:
strlen(str)=11, wcslen(wstr)=6
strlen 的运转后果显然不准确,由于它把一个字节作为一个字符盘算,而 wcslen 把两个字节作为一个字符盘算。
留意:wcslen 在 string.h 和 wchar.h 头文件中均有阐明。
保护一个版本的源代码
在 Windows NT 以前的操作零碎中,乃至包含 Windows 98,对宽字符的支撑都不是很好,所以大多状况下运用ASCII编码。Windows NT 推出今后,曾经从底层支撑了Unicode,所以在 Windows NT 上的程序大多运用Unicode。
假如你愿望程序可以在各类版本的Windows操作零碎中运转,那么就需求保护两个版本的源代码,ASCII 版和 Unicode 版。ASCII 字符和 Unicode 字符的界说、运用都纷歧样,要想在一个版本的源代码中做兼容处置会十分艰苦,要做少量的任务,对程序员来说几乎是恶梦。
不外,Windows 又为我们做了一件坏事,曾经处置了兼容性成绩。它是怎样做到的呢?
例如关于字符串,ASCII 中运用 char 来界说,而 Unicode 中运用 wchar_t 来界说,而且需求添加前缀L。那么在 windows.h 头文件中(或许是它包括的其他头文件)就如许来处置:
#ifdef UNICODEtypedef wchar_t TCHAR; #define TEXT(quote) L##quote#else typedef char TCHAR#define TEXT(quote) quote#endif
我们在源码中可以如许来运用:
TCHAR str[] = TEXT("C言语中文网");
假如是Unicode版,也就是界说了UNICODE宏,那么下面的语句等价于:
wchar_t str[] = L"C言语中文网";
假如是ASCII,也就是没有界说UNICODE宏,那么等价于:
char str[] = "C言语中文网";
在Windows中,到处可见如许的处置。固然古代操作零碎都曾经支撑Unicode,无需再思索与ASCII的兼容性成绩,然则仍然要为这些汗青成绩支付价值。
总结:因为各类各样的缘由,我们优先运用Windows界说的数据类型、宏、构造体等,如许编写的程序兼容性较好,不必思索ASCII和Unicode的成绩。但这也带来了一个应战,就是要熟习Window界说的数据类型、宏、构造体等。