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

从int变量提取字节时高位字节符号扩展异常问题排查

问题描述

尝试从一个int变量中提取4个char值,但所有尝试均得到相同结果:高低字的低字节读取正确,但高字节被扩展为int时填充了全1。以下是使用GCC编译的测试代码:

#include <stdio.h>

#define PRINT   printf("b1 %u\n", bb1);\
            printf("b2 %u\n", bb2);\
            printf("b3 %u\n", bb3);\
            printf("b4 %u\n", bb4)

typedef union{
    int integer;
    struct{
        char b1;
        char b2;
        char b3;
        char b4;
    };
}bytes;

typedef struct{
    char b1:8;
    char b2:8;
    char b3:8;
    char b4:8;
}bitfield;


int main()
{
    int a;
    printf("int size = %u\n", a=sizeof(int));
    printf("char size = %u\n", a=sizeof(char));
    bytes in_union;
    bitfield in_struct;
    // values stored in bytes 
    // hword.hi 240 hword.lo 15
    // lword.hi 129 lword.lo 126
    int value = 4027548030;
    
    // #1 solution with union
    in_union.integer = value;
    
    char bb1 = in_union.b1;
    char bb2 = in_union.b2;
    char bb3 = in_union.b3;
    char bb4 = in_union.b4;
    PRINT;
    
    // #2 with pointer to union
    char* uptr;
    uptr = (char*)&in_union;
    bb1 = *uptr;
    bb2 = *(uptr+1);
    bb3 = *(uptr+2);
    bb4 = *(uptr+3);
    PRINT;
    
    // #3 with void pointer to union
    void* vptr;
    vptr = &in_union;
    bb1 = *(char*)vptr;
    bb2 = *(char*)(vptr+1);
    bb3 = *(char*)(vptr+2);
    bb4 = *(char*)(vptr+3);
    PRINT;
    
    // #4 with pointer to value variable
    char* ptr = (char*)&value;
    bb1 = *ptr;
    bb2 = *(ptr+1);
    bb3 = *(ptr+2);
    bb4 = *(ptr+3);
    PRINT;
    
    // #5 with bitfield
    in_struct.b1 = (char)value;
    in_struct.b2 = (char)(value>>8);
    in_struct.b3 = (char)(value>>16);
    in_struct.b4 = (char)(value>>24);
    bb1 = in_struct.b1;
    bb2 = in_struct.b2;
    bb3 = in_struct.b3;
    bb4 = in_struct.b4;
    PRINT;
    
return 0;
}

实际输出:

b1 126
b2 4294967169
b3 15
b4 4294967280

预期输出:

b1 126
b2 129
b3 15
b4 240
问题原因与解决方法

核心原因

问题出在**char类型的符号扩展**:

  • 多数编译器(包括GCC)中,char默认是有符号类型(signed char)。
  • 当提取的字节值大于127(比如129、240)时,这些值在有符号char中会被解析为负数(129对应-127,240对应-16)。
  • 把这些负数的char传给printf的%u(无符号整数)格式符时,会先进行整数提升:负数以符号扩展方式填充高位为全1,最终转换为超大的无符号整数,这就是你看到的异常结果。

解决方法

有两种直接有效的修复方式:

方法1:使用unsigned char替代char

将代码中所有char类型替换为unsigned char,包括结构体、联合体成员及临时变量:

typedef union{
    int integer;
    struct{
        unsigned char b1;
        unsigned char b2;
        unsigned char b3;
        unsigned char b4;
    };
}bytes;

typedef struct{
    unsigned char b1:8;
    unsigned char b2:8;
    unsigned char b3:8;
    unsigned char b4:8;
}bitfield;

// 临时变量同步修改
unsigned char bb1, bb2, bb3, bb4;

unsigned char会把所有字节值当作无符号数处理,不会产生符号扩展,传递给%u时能正确输出原始字节值。

方法2:输出时强制转换为unsigned char

如果不想修改类型定义,可在printf中把char强制转换为unsigned char,再转为unsigned int匹配格式:
修改PRINT宏:

#define PRINT   printf("b1 %u\n", (unsigned int)(unsigned char)bb1);\
                printf("b2 %u\n", (unsigned int)(unsigned char)bb2);\
                printf("b3 %u\n", (unsigned int)(unsigned char)bb3);\
                printf("b4 %u\n", (unsigned int)(unsigned char)bb4)

先转换为unsigned char消除符号扩展,再转为unsigned int适配%u的格式要求。

注:你的预期输出中bb2应为129而非127,属于注释对应值的笔误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 01:17:02