• 被坑惨了,建议大家在编程时尽量用UTF-8而不要用GBK
  • 发布于 2个月前
  • 120 热度
    4 评论
  • DuXing
  • 7 粉丝 55 篇博客
  •   
最近在把我用 C 写的一批 Linux 工具移植到 Windows 上,在字符编码上遇到了大坑。
举个简单的例子:数文件层级。
在 Linux 上,我们数斜杠数量就好。
在 Windows 上,再加上反斜杠,应该就好了。——我是这样想的。
#include <stdio.h>
int main(int argc, char *argv[]) {
    int level;
    const char *p;
    if (argc < 2) {
        return 1;
    }
    for (level = 0, p = argv[1]; *p; p++) {
        if (*p == '/' || *p == '\\') {
            level++;
        }
    }
    printf("%d\n", level);
    return 0;
}
用 MinGW 的 GCC 编译一下,然后跑几个用例:
gcc -o getlevel.exe getlevel.c
C:\>getlevel C:\浙江省\宁波市\北仑区\小港街道.txt
4
C:\>getlevel C:\浙江省\宁波市\北仑区\大碶街道.txt
5
天塌了,这么简单的代码竟然出了 bug 。原来 碶 的 编码是 {0xb4, 0x5c},其中 0x5c 和反斜杠的 ASCII 编码一模一样。GBK 的第一字节兼容 ASCII ,但第二字节的范围是 0x40 ~ 0xfe,与 ASCII 的 0x00 ~ 0x7f 重叠。BUG 就这么诞生了。

UTF-8 没有这个问题的原因是:只要字节范围在 0x00 ~ 0x7f,那么就一定是 ASCII ,因为后续字节都避开了这个范围。虽然中文编码比 GB 系列长了,但是这个设计确实省了很多事。包括 strstr() strcmp() 之类的都不会出现奇奇怪怪的 bug 。

或许我应该使用 wmain() 然后获取 wchar_t,但是 wmain() 是 Windows 特有的东西,这样做就没法和 Linux 公用同一套代码了。目前加上了 mbtowc() 作为修复。原本简洁的代码变得十分复杂。说到这又不得不吐槽下 Windows 的各种奇怪 API 了,不知道它是如何存活到现在的...
用户评论