#define _CRT_SECURE_NO_WARNINGS

/*多字节转宽字节*/

int unsafe_mbstowcs()
{
    // 设置当前的 locale 为用户环境变量指定的 locale
    setlocale(LC_ALL, "");
    // 定义多字节字符串
    const char* mbstr = "Hello, 世界!";
    // 计算需要的缓冲区大小
    size_t wcs_len = mbstowcs(NULL, mbstr, 0) + 1;
    // 分配宽字符缓冲区
    wchar_t* wcs = (wchar_t*)malloc(wcs_len * sizeof(wchar_t));
    if (wcs == NULL)
    {
        perror("malloc");
        return 1;
    }

    // 进行转换
    mbstowcs(wcs, mbstr, wcs_len);
    // 打印宽字符字符串
    wprintf(L"%ls\n", wcs);
    // 释放内存
    free(wcs);

    return 0;
}

int safe_mbstowcs_s()
{
    // 设置当前的 locale 为用户环境变量指定的 locale
    setlocale(LC_ALL, "");

    // 定义多字节字符串
    const char* mbstr = "Hello, 世界!";
    // 计算需要的缓冲区大小
    size_t wcs_len /*= strlen(mbstr) + 1*/; // 其实直接这样也可以,大一点空间也无所谓
    // 首先获取所需的宽字符数量
    mbstowcs_s(&wcs_len, NULL, 0, mbstr, _TRUNCATE);
    // 分配宽字符缓冲区
    wchar_t* wcs = (wchar_t*)malloc(wcs_len * sizeof(wchar_t));
    if (wcs == NULL)
    {
        perror("malloc");
        return 1;
    }

    // 安全转换
    size_t retVal = 0;
    // retVal:参数返回值,函数是否成功。
    // wcs: 宽字节缓存区地址。
    // wcs_len:是宽字符的数量,不是字节数
    // mbstr: 源多字节地址
    // _TRUNCATE:表示遇到字符串最后的空为止, 需要转换的源多字节最大数量(不包含最后的\0)
    auto errVal = mbstowcs_s(&retVal, wcs, wcs_len, mbstr, _TRUNCATE);
    //auto errVal = mbstowcs_s(&retVal, wcs, wcs_len, mbstr, strlen(mbstr)-4);// 只打印出:Hello, 世
    // 打印宽字符字符串
    wprintf(L"%ls\n", wcs);
    // 释放内存
    free(wcs);

    return 0;
}

int win_multibytetowidechar()
{
    // 设置当前的 locale 为用户环境变量指定的 locale
    setlocale(LC_ALL, "");

    unique_ptr<char[]> sBufArr(new char[50]{ 0 });
    char* sBuf = sBufArr.get();
    strcpy_s(sBuf, 50, "Hello, World! 你好,世界!");
    size_t sBufSize = strlen(sBuf) + 1; // must add 1

    //获取输出缓存大小
    //VC++ 默认使用ANSI,故取第一个参数为CP_ACP
    INT dBufSize = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, NULL, 0);
    printf("需要wchar_t%u个\n", dBufSize);

    unique_ptr<wchar_t[]> dBufArr(new wchar_t[dBufSize] {0});
    wchar_t* dBuf = dBufArr.get();
    wmemset(dBuf, 0, dBufSize);

    //进行转换
    int nRet = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, dBuf, dBufSize);
    if (nRet <= 0)
    { // 失败
    }
    else
    {// 成功
        wprintf(L"nRet = %d, mstr = %ls\n", nRet, dBuf);
    }

    return nRet;
}

/*宽字节转多字节*/
int unsafe_wcstombs()
{
    const wchar_t* wc = L"hi, 你好!";
    auto size_wc = 2 * (wcslen(wc) + 1);
    char* mb = (char*)malloc(size_wc);

    size_t ret = wcstombs(mb, wc, size_wc);
    printf("ret=%d %s\n", ret, mb);

    free(mb);
    return ret;
}

int safe_wcstombs_s()
{
    const wchar_t* wstr = L"hi, 你好!";
    size_t len /*= wcslen(wstr) + 1*/; // 其实直接这样也可以,大一点空间也无所谓
    // 首先获取所需的多字节数量 
    wcstombs_s(&len, NULL, 0, wstr, _TRUNCATE);
    /*len *= 2;*/
    char* mb = (char*)malloc(len);

    size_t ret_cnt;
    errno_t res = wcstombs_s(&ret_cnt, mb, len, wstr, _TRUNCATE);
    if (res != 0)
    {//fail
    }
    else
    {//success
        printf("%d  %s\n", ret_cnt, mb);
    }

    free(mb);
    return res;
}

int win_widerchartomultibyte()
{
    // 设置当前的 locale 为用户环境变量指定的 locale
    setlocale(LC_ALL, "");

    unique_ptr<wchar_t[]> sBufArr(new wchar_t[50]{ 0 });
    wchar_t* sBuf = sBufArr.get();
    wcscpy_s(sBuf, 50, L"Hello, World! 你好,世界!");
    size_t sBufSize = wcslen(sBuf) + 1;

    //获取输出缓存大小 NULL 表示到字符串结尾
    INT dBufSize = WideCharToMultiByte(CP_OEMCP, 0, sBuf, -1, NULL, 0, NULL, FALSE);
    printf("需要char%u个\n", dBufSize);

    unique_ptr<char[]> dBufArr(new char[dBufSize] {0});
    char* dBuf = dBufArr.get();
    memset(dBuf, 0, dBufSize);

    //进行转换
    int nRet = WideCharToMultiByte(CP_OEMCP, 0, sBuf, -1, dBuf, dBufSize, NULL, FALSE);
    if (nRet <= 0)
    { // 失败
    }
    else
    {// 成功
        printf("nRet = %d, mstr = %s\n", nRet, dBuf);
    }

    return nRet;
}

输出:

Hello, 世界!
Hello, 世界!
需要wchar_t21个
nRet = 21, mstr = Hello, World! 你好,世界!
ret=10 hi, 你好!
11  hi, 你好!
需要char26个
nRet = 26, mstr = Hello, World! 你好,世界!
请按任意键继续. . .