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

C语言中char类型存储UTF-8字符时十六进制输出异常问题咨询

为什么UTF-8字符的字节输出会带ffffff前缀?

嘿,这个问题我之前也碰到过,其实核心原因和C语言里char类型的符号属性有关,咱们一步步拆解来看:

1. 先搞懂char的默认类型

在绝大多数编译器中,char默认是有符号类型(signed char),它的取值范围是 -128 到 127(对应十六进制 0x80 到 0x7F)。而UTF-8编码的非ASCII字符,比如你例子里的ü,它的两个字节是0xC3和0xBC,这两个值都大于0x7F(也就是127),所以会被当作负数存储在signed char里:

  • 0xC3 对应的十进制是195,超过127,所以转成 -61(计算方式:195 - 256 = -61)
  • 0xBC 对应的十进制是188,转成 -68(188 - 256 = -68)

2. 符号扩展是罪魁祸首

当你把char类型的变量传给printf的%x格式符时,会发生两件事:

  • 可变参数函数(比如printf)会把小于int的类型自动提升为int
  • 对于有符号的负数,提升时会进行符号扩展:也就是把最高位的符号位(这里是1)填充到所有新增的高位字节里。

拿0xC3对应的signed char(值为-61)来说,它的二进制是11000011,提升为32位int后,就变成了11111111 11111111 11111111 11000011,对应的十六进制就是ffffffc3——这就是你看到的前缀来源。

3. 为什么&0xFF能修复?

&0xFF本质是做了一个位掩码操作:0xFF的二进制是00000000 00000000 00000000 11111111,和扩展后的32位int按位与之后,会把高位的所有1都清零,只保留低8位的原始字节值,也就是0xC3和0xBC,这样输出就符合预期了。

两种更优雅的解决方法

除了用&0xFF,你还可以从根源上避免符号扩展:

  • 把数组声明为unsigned char类型:
    unsigned char test[3] = "ü";
    for (int x = 0; x < 3; x++){
        printf("%x\n", test[x]);
    }
    
  • 在输出时强制转换为unsigned char:
    char test[3] = "ü";
    for (int x = 0; x < 3; x++){
        printf("%x\n", (unsigned char)test[x]);
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 08:52:42