我找到了一个打印签名字符的最大值和最小值的程序。虽然我们已经在课堂上学习了位操作,但我并不了解所有操作员何时组合在一起。
[disabled]='...'
例如,我知道〜翻转位和>>将它们移到右边。所以我相信〜0>> 1,翻转所有位并将它们移动到正确的一个位置。但是为什么我们减去1,我认为两个补码会增加一个?
答案 0 :(得分:0)
表达式前面有一个-
运算符,用于计算最小值:
-(char)((unsigned char) ~0 >> 1) - 1
因此,表达式中操作数评估的顺序为:
~0 >> 1
并将结果转换为unsigned char
,char
,-
运算符和-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
,这是毫无意义的。转换时该值将保持不变,但
char
是与signed char
不同的类型,而前者不一定是签名类型,因此转换为char
无论如何都无法用于与范围相关的任何目的值signed char
。
结果表达式将被转换(进一步)到int
类型,然后再将其传递给printf()
。
尽管如此,显示的值确实是可以表示为signed char
的最大值。
最小值的表达式只产生一个小于最大值的倒数。这是正确的最小值 ,前提是signed char
以二进制补码形式表示 。虽然我知道的每个现代实现确实使用二元补码形式用于有符号整数,但C明确允许另外两种形式,两种形式都将最小值等于其最大值的倒数。该程序将在具有signed char
的表示的平台上产生错误的最小值。
答案 3 :(得分:-1)
因为零被认为是正数,所以有128个正值0到127 然而,负数从-1开始,因此它有128个负值-1到-128。
短暂的正面从0开始,所以它只得到127,但负从-1开始,所以它到达-128
这就是0111111 = 127但1000000 = -128;
的原因