按位运算w / signed chars

时间:2016-09-24 22:51:35

标签: c bit-manipulation

我找到了一个打印签名字符的最大值和最小值的程序。虽然我们已经在课堂上学习了位操作,但我并不了解所有操作员何时组合在一起。

[disabled]='...'

例如,我知道〜翻转位和>>将它们移到右边。所以我相信〜0>> 1,翻转所有位并将它们移动到正确的一个位置。但是为什么我们减去1,我认为两个补码会增加一个?

4 个答案:

答案 0 :(得分:0)

表达式前面有一个-运算符,用于计算最小值:

-(char)((unsigned char) ~0 >> 1) - 1

因此,表达式中操作数评估的顺序为:

  1. 计算~0 >> 1并将结果转换为unsigned char
  2. 将之前的结果投放到char
  3. 使用-运算符和
  4. 更改上一结果的符号
  5. 减去一个(-1)以获得最小可能值(0值被视为正值)。

答案 1 :(得分:0)

  • (unsigned char) ~0所有位1(最大正unsigned char
  • >> 1关闭最高位,用于符号(最大正signed char
  • -(char)否认该值为char(注意:应为signed char
  • - 1用于现在的负值,因为在两个补码中,最负值是幅度大于最大值的值(因为零值的符号位关闭,并且在两个补充中没有"负零"

答案 2 :(得分:0)

取最大值,将括号添加到原始表达式以阐明操作的顺序,原始表达式变为

(char) (((unsigned char) (~0)) >> 1)

首先,~0产生类型int的值(因为常量0具有该类型),其位模式由所有1组成(不包括任何填充位) )。这将是一个负数,因为它的符号位将被设置。

强制转换将该值转换为unsigned char类型,这会导致该类型的值包含所有位1

但是signed char类型的值比unsigned char少一个,因为它的表示与unsigned char的大小相同,既没有填充位,也没有signed char。 1}}使用其中一个位作为符号位。向右移动一个位置会移出额外值位,从而产生unsigned char,其值为signed char类型可容纳的最大值。

然后将结果转换为类型char,这是毫无意义的。转换时该值将保持不变,但

  1. char是与signed char不同的类型,而前者不一定是签名类型,因此转换为char无论如何都无法用于与范围相关的任何目的值signed char

  2. 结果表达式将被转换(进一步)到int类型,然后再将其传递给printf()

  3. 尽管如此,显示的值确实是可以表示为signed char的最大值。

    最小值的表达式只产生一个小于最大值的倒数。这是正确的最小值 ,前提是signed char以二进制补码形式表示 。虽然我知道的每个现代实现确实使用二元补码形式用于有符号整数,但C明确允许另外两种形式,两种形式都将最小值等于其最大值的倒数。该程序将在具有signed char的表示的平台上产生错误的最小值。

答案 3 :(得分:-1)

因为零被认为是正数,所以有128个正值0到127 然而,负数从-1开始,因此它有128个负值-1到-128。

短暂的正面从0开始,所以它只得到127,但负从-1开始,所以它到达-128

这就是0111111 = 127但1000000 = -128;

的原因