今天遇到Windows 10里安装的Ubuntu(WSL)的缺点

随着技术的发展,越来越多开发者转向使用 Windows Subsystem for Linux(WSL)在 Windows 10 上进行开发,也就是说不用虚拟机,不用准备多一台电脑,只需要在Windows 10/11 里安装 WSL 就能体验 Linux 系统。因此我在 Win10 系统里安装了Ubuntu 20 系统学习 Linux 基础,可以用来编译 C / C++ 代码,体验同一个代码编译运行与 Windows 环境下的差别。

之前就听说 WSL 有一些潜在的限制,无论性能还是功能都不能完全取代裸机 Linux 系统。今天就被我逮到 WSL 下的 Ubuntu 的一个缺点:输出宽字符串(wide string)时失败。

比如下面一段把普通字符串转换成宽字符串的 C 代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>
    
int main() {
    
    
	// Windows环境下要设为 setlocale(LC_ALL, "en-US.UTF-8");
	// Linux环境下设为 setlocale(LC_ALL, "");
	// 设置不当的话,转换后的宽字符串长度不正确
    setlocale(LC_ALL, "");

    char* str = "22年2月22日";
    int len = strlen(str);
    printf("narrow string: %s\n", str);
    printf("narrow string length: %d\n", len);

    wchar_t* wstr = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
    size_t wlen = mbstowcs(wstr, str, len+1);

    wprintf(L"wide string: %ls\n", wstr);
    printf("wide string length: %zu\n", wlen);
    for(size_t i=0; i<wlen; i++)
        wprintf(L"%lc\t%d\n", wstr[i], (int)wstr[i]);

    free(wstr);
    return 0;
}

这段代码演示了普通字符串“22年2月22日”默认状态下的长度是14字节,但这个长度是机内码的长度,而人类理解的长度应该是8才对,在Python和Java里也得出8,为了使 C 代码获得与Python、Java代码计算一样的长度,必须把它转换成宽字符串格式。代码接下来输出各个字符值。在 Windows 环境下,必须在主程序里设置本地代码页环境setlocale(LC_ALL, "en-US.UTF-8");或者setlocale(LC_ALL, "zh-CN.UTF-8");,使用 clang 编译运行的结果才能正常输出宽字符串长度为8:
在这里插入图片描述
到了 WSL 的 Ubuntu 环境,由于Ubuntu终端的字符编码默认是UTF-8,因此主程序中要把 LC_ALL后面的字符串置空:setlocale(LC_ALL, "");,否则计算出来的宽字符串长度也不正确。然后编译运行:

在这里插入图片描述
经过设置setlocale(LC_ALL, "");以及mbstowcs转换后的宽字符串长度是8,正确。但是接下来的 wprintf 语句无法输出转换后的字符串以及每个字符对应的值。我尝试了各种办法修改 wprintf 、 printf 、setlocale 语句,但输出结果无济于事,令人百思不得其解。

直到后来我在安卓手机上安装了Termux(一款运行于安卓系统的 Linux 模拟器),然后在手机上运行 clang 编译再运行 ~~ 在手机里运行结果却正常了。

在这里插入图片描述

换了环境,豁然开朗!

由此可见 Windows 10 的 WSL(Ubuntu) 在处理特定操作时确实有其局限性。在遇到令人摸不着头脑的问题时不妨切换到其它 Linux 环境再试试。

猜你喜欢

转载自blog.csdn.net/Scott0902/article/details/134466486