还有两件事:
(1) 你得到了那些奇怪的数字,因为你机器上的普通字符(像很多一样)显然是签名的。您可以通过转换为unsigned char 来查看“真实”字节:
char *a = "Ā";
printf("%u %u\n", ((unsigned char *)a)[0], ((unsigned char *)a)[1]);
printf("%x %x\n", ((unsigned char *)a)[0], ((unsigned char *)a)[1]);
或一直使用unsigned char:
unsigned char *u = "Ā";
printf("%x %x\n", u[0], u[1]);
%u 版本打印196 128,%x 版本打印c4 80。
(2) 我不确定您所说的“不使用 C11 中的 <uchar.h>”是什么意思,但如果您不想手动进行 UTF-8 转换,您可以转换“多字节字符串”使用库函数 mbtowc 来自 <stdlib.h>:
wchar_t wc;
mbtowc(&wc, a, strlen(a));
printf("%d %x\n", wc, wc);
这会在我的机器上打印256 100,因为Ā 是U+0100。
另一个有用的函数是mbstowcs,它同时对多个字符执行此操作:
char *mbs = "Daß ist sehr schön";
printf("%s\n", mbs);
wchar_t wcs[20];
int n = mbstowcs(wcs, mbs, 20);
for(int i = 0; i < n; i++)
printf("%3d %x %lc\n", wcs[i], wcs[i], wcs[i]);
但是,当使用 mbtowc 和 mbstowcs 之类的函数时,您必须记住它们不一定必须处理 UTF-8 和 Unicode。除了 Unicode,还有宽字符编码,以及 UTF-8 以外的多字节表示。事实上,要让这些功能在我的机器上“正确”工作,我必须先调用
setlocale(LC_CTYPE, "");
告诉他们可以使用我的语言环境设置(即en_US.UTF-8),而不是默认的“C”语言环境,它不假定为 Unicode。