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

通过char指针提取16位数据的8位输出异常,寻求技术帮助

问题分析与解决方案

你的问题核心出在有符号char的符号扩展和内存字节序两个点上,咱们一步步拆解:

1. 为什么会出现FFFFFF前缀?

大部分编译器默认char是有符号类型(signed char),它的取值范围是-128~127。当你用char*去解引用内存中的字节时:

  • 如果字节值在0x80~0xFF之间(比如0xAA、0xBB),会被当作负数(比如0xAA对应的有符号char值是-86)
  • 在调用printf("%X")时,这个char会被自动提升为int类型,负数的符号扩展会把高位全部补1,就出现了FFFFFFAA这种输出。
  • 而0x34、0x12这类小于0x80的字节,作为有符号char是正数,提升为int时高位补0,所以输出正常。

2. 为什么字节顺序和预期不符?

这是小端字节序导致的:大部分现代CPU是小端模式,存储unsigned short时会把低字节放在内存低地址,高字节放在高地址。比如0xCCBB会被存成0xBB(低地址)、0xCC(高地址),所以你用char*遍历的时候会先拿到0xBB,再拿到0xCC,和你预期的CC在前、BB在后相反。


解决方案

方案一:改用unsigned char*遍历(最直接)

把指针类型改成无符号字符指针,这样解引用得到的字节不会被当作负数,提升为int时高位补0,彻底避免符号扩展:

#include <stdio.h>

int main() {
    unsigned short int buf[50] = {0};
    unsigned char *ptr = (unsigned char*)buf; // 替换为unsigned char*
    
    buf[0] = 0xAAAA;
    buf[1] = 0xCCBB;
    buf[2] = 0x1234;
    buf[3] = 0xABCD;
    
    for(int j = 0; j < 8; j++) {
        printf("%X\t", *ptr);
        ptr++;
    }
    return 0;
}

输出结果(小端环境下):AA AA BB CC 34 12 CD AB

方案二:强制转换为无符号字符输出

如果不想改指针类型,在printf时把解引用的值强制转成unsigned char,同样能避免符号扩展:

printf("%X\t", (unsigned char)*ptr);

方案三:按16位数据的高位到低位输出(修正字节序)

如果你的目标是先输出每个unsigned short的高字节,再输出低字节,而不是按内存存储顺序遍历,可以直接操作16位数据:

#include <stdio.h>

int main() {
    unsigned short int buf[50] = {0};
    
    buf[0] = 0xAAAA;
    buf[1] = 0xCCBB;
    buf[2] = 0x1234;
    buf[3] = 0xABCD;
    
    for(int j = 0; j < 4; j++) {
        // 提取高8位:右移8位后转无符号char
        printf("%X\t", (unsigned char)(buf[j] >> 8));
        // 提取低8位:与0xFF掩码后转无符号char
        printf("%X\t", (unsigned char)(buf[j] & 0xFF));
    }
    return 0;
}

输出结果:AA AA CC BB 12 34 AB CD,完全符合你对每个16位数据的高位到低位输出预期。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:07:53