You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Linux下用GCC打印Unicode字符及UTF-16文件打印的问题

问题分析与解决方案

代码存在的核心问题

  • -fshort-wchar与glibc标准IO不兼容:Linux系统默认wchar_t是32位,glibc的printf("%ls")等函数是针对32位wchar_t实现的。你用-fshort-wchar强制将wchar_t改为16位后,printf无法正确解析16位宽字符数据,导致后续输出无内容。
  • 宽字符数组初始化错误:wchar_t sample1[] = { L"..." };的写法错误——花括号把宽字符串字面量(本质是const wchar_t*)当成单个元素存入数组,实际得到的是仅包含指针的数组,而非预期的宽字符序列,这也会导致打印异常。

修复当前打印问题的步骤

1. 移除-fshort-wchar编译选项

Linux下处理宽字符应遵循系统默认的32位wchar_t,不要强制修改宽度。如果需要兼容Windows的UTF-16数据,应在读取后做编码转换,而非修改wchar_t的宽度。

2. 修正宽字符数组初始化

去掉多余的花括号,正确声明宽字符数组:

wchar_t sample1[] = L"Sample TEXT\\自己人自己人人       AZZZZZZZA己中国中中中\n";

3. 验证修复后的代码

修改后的完整代码:

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_ALL, "en_US.UTF-8");
    wchar_t sample1[] = L"Sample TEXT\\自己人自己人人       AZZZZZZZA己中国中中中\n";
    printf("AAAA\n");
    printf("%ls", L"ABCD");
    printf("%ls", sample1);
    return 0;
}

编译命令:

gcc test.c -o test

运行后就能正常输出所有宽字符内容。

处理Windows UTF-16文件的读取与打印

Windows下的UTF-16文件通常带BOM(字节顺序标记),读取时需先处理字节序,再将UTF-16转换为Linux终端支持的UTF-8输出,这种方式比依赖宽字符函数更可靠:

示例代码(读取UTF-16文件并打印)

#include <stdio.h>
#include <stdlib.h>
#include <iconv.h>
#include <string.h>

#define BUFFER_SIZE 1024

int main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <utf16-file>\n", argv[0]);
        return 1;
    }

    FILE *fp = fopen(argv[1], "rb");
    if (!fp) {
        perror("fopen failed");
        return 1;
    }

    // 跳过UTF-16 BOM(如果存在)
    unsigned char bom[2];
    if (fread(bom, 1, 2, fp) == 2) {
        if (!(bom[0] == 0xFF && bom[1] == 0xFE) && !(bom[0] == 0xFE && bom[1] == 0xFF)) {
            // 无BOM或BOM无效,重置文件指针
            fseek(fp, 0, SEEK_SET);
        }
    }

    // 初始化iconv,将UTF-16LE(Windows常用)转换为UTF-8
    iconv_t cd = iconv_open("UTF-8", "UTF-16LE");
    if (cd == (iconv_t)-1) {
        perror("iconv_open failed");
        fclose(fp);
        return 1;
    }

    char in_buf[BUFFER_SIZE], out_buf[BUFFER_SIZE * 2];
    size_t in_left, out_left;
    char *in_ptr, *out_ptr;

    while ((in_left = fread(in_buf, 1, BUFFER_SIZE, fp)) > 0) {
        in_ptr = in_buf;
        out_ptr = out_buf;
        out_left = sizeof(out_buf);

        if (iconv(cd, &in_ptr, &in_left, &out_ptr, &out_left) == (size_t)-1) {
            perror("iconv failed");
            break;
        }

        // 输出转换后的UTF-8内容
        fwrite(out_buf, 1, sizeof(out_buf) - out_left, stdout);
    }

    iconv_close(cd);
    fclose(fp);
    return 0;
}

编译命令:

gcc utf16_to_utf8.c -o utf16_to_utf8 -liconv

运行方式:

./utf16_to_utf8 your_windows_utf16_file.txt

说明

  • 使用iconv库进行编码转换,这是Linux系统处理不同编码的标准工具。
  • 处理UTF-16字节序:Windows默认是UTF-16LE,代码中优先按此转换;如果文件是UTF-16BE,只需将iconv_open的第二个参数改为"UTF-16BE"。
  • 转换为UTF-8后直接用fwrite输出,无需依赖宽字符函数,适配性更强。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 18:33:11