从unsigned char(Little endian)

时间:2017-09-11 15:30:26

标签: c bit-manipulation

如何从unsigned char中检索负值。

说我有无符号的字符,我很有趣,只想得到第1个6位。现在这些6位可以具有从其他函数填充的正值或负值。我想提取相同的价值。 我可以使用0x3F成功提取正值。但是,如果它有负值示例怎么样

signed char my_6bitfunc(  unsigned char *val )
{
   unsigned char temp = *val & 0x3F;
   return temp;
}

// somewhere in main
 int main()
{
    signed char valneg = -31 ;
    signed char valpos = 31 ;

   signed char a = my_6bitfunc( &valneg );
    signed char b = my_6bitfunc( &valpos );

    printf("  val neg %d\n", a );  // not -31 but 33 ?
    printf(" val positive %d\n", b );
}

O / P
期望值a = -31实际值= 33为什么?错
期望值b = 31实际值= 31正确。

2 个答案:

答案 0 :(得分:3)

要签署扩展二进制补码字段,请使用((x ^ N) - N) - 其中N是符号位的数字表示,例如,对于16位,为32768。

signed char my_6bitfunc (unsigned char *val)
{
   unsigned char temp = *val & 0x3FU;
   return ((signed char )(temp ^ 0x20U)) - 0x20;
}

答案 1 :(得分:0)

嗯,你不能掩盖负数的2个高位。

为什么不呢?

好吧,在2&2补码和8位char变量(最常见)中,你有:

-31 -> 11100001

如果你用0x3f掩饰,你就会得到

00100001

对于8位2的补码有符号数正好是33。因此,您的程序打印33。

通常,您无法在计算机中使用数字的基本表示。在大多数系统上,无法用6位表示有符号数字并使用8位格式打印。这是不可能的。

但是,您可以编写一个函数,将8位有符号数的范围限制为6位有符号数。 C标准为您提供了在具有不同位数的类型之间进行转换时如何完成的线索。你可以实现类似的转换。

6位有符号2的补码数可以保持-32到31.因此,如果转换函数-75的输入你应该继续向输入加31 + 1(即MAX + 1),直到它为止。在有效范围内。

-75 + (31+1) = -43 
-43 + (31+1) = -11 (which is in range)

但是在二进制级别,您需要将其保存为11110101,因为您的计算机很可能使用8位作为其最小整数类型。

如果您知道否定输入的范围介于-32和-1之间(并且在输入小于-32时不关心转换),则可以保留二进制负数的模式不变。像:

#include <stdio.h>

signed char my_6bitfunc(  signed char *val )
{
    if (*val < 0) return *val;  // Add this line
    return *val & 0x3F;;
}

 int main()
{
    signed char valneg = -31 ;
    signed char valpos = 31 ;

    signed char a = my_6bitfunc( &valneg );
    signed char b = my_6bitfunc( &valpos );

    printf("  val neg %d\n", a );  // not -31 but 33 ?
    printf(" val positive %d\n", b );
}

输出:

  val neg -31
 val positive 31