Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从无符号字符(小尾端)检索正或负n位_C_Bit Manipulation - Fatal编程技术网

C 从无符号字符(小尾端)检索正或负n位

C 从无符号字符(小尾端)检索正或负n位,c,bit-manipulation,C,Bit Manipulation,如何从无符号字符中检索负值 假设我有一个未签名的字符,我把它传递给了fun,只想得到前6位。现在,这些6位可以从其他函数填充正值或负值。我想提取相同的值。 我可以使用0x3F成功提取正值。但是如果它有负值呢 signed char my_6bitfunc( unsigned char *val ) { unsigned char temp = *val & 0x3F; return temp; } // somewhere in main int main() {

如何从无符号字符中检索负值

假设我有一个未签名的字符,我把它传递给了fun,只想得到前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正确。

若要对两位补码字段进行符号扩展,请使用
((x^N)-N)
——其中
N
是符号位的数字表示,例如,对于16位,32768

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

嗯,你不能把负数的两个高位遮住

为什么不呢

在2的补码和8位字符变量(最常见)中,您有:

-31 -> 11100001
如果您使用0x3f屏蔽,您将获得

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

一般来说,你不能在电脑里玩数字的基本表示法。在大多数系统中,无法用6位表示有符号的数字并用8位格式打印。这是不可能的

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

6位有符号2的补码可以保存-32到31。因此,如果转换函数的输入为-75,则应继续向输入中添加31+1(即最大+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 );
}

my6bitfunc
中,为什么
temp
没有签名?@MotKohn,即使签名也没有任何区别。我将返回签名字符。我想我在这里看到的是额外的操作,比如xor或类似的操作,它给了我期望的值,但不知道要添加什么,如果用-75?@4386427 re调用函数,你想要什么结果。2的补码,然后类似于
(unsigned char)~(i-1)
@4386427-75大于6位,所以代码不需要关心。Max vaue posiitve应该只有63岁,我想如果我们用未签名的6比提做了类似的事情temp=(temp^0x20)-0x20;现在得到期望值。但仍然无法理解为什么我们要对它进行异或和减法运算,以及如何得到正确的值?例如0x3D XOR 0x20=0x1F(12月31日)。现在1F-0X20。。。我知道我得到了正确的值,但你能给我解释一下吗。当我在计算器中减去1F-0x20,我得到111111。返回带符号的temp如何使其正确?0x20是符号位;您可以认为它的值为-2^5,而其他位的值为2^4 2^3。。。2^0. 异或反转符号位,即第5位;如果是零,我们加了2^5;如果是1,我们减去2^5。现在,通过减去2^5,我们恢复了我们在符号位为0时添加的2^5,并减去了符号位为1时我们需要的2^5。感谢解释请注意,
111111111111
是-1的两个补码表示,这是
0x1F-0x20
所期望的。试着加上-2^5+2^4+2^3+2^2+2^1+2^0(这里^的意思是“的幂”,而不是像在C中那样的XOR)。我感兴趣的是6它的正负值由一些函数填充。其他mSb由其他函数填充。所以我需要用有符号和无符号val提取前6位
  val neg -31
 val positive 31