按位移位运算符的ISO C99标准对左移有如下说明:E1〈〈E2的结果是E1左移E2比特位置;空出的位用零填充。如果E1是无符号类型,则结果的值为E1× 2 E2,比结果类型中可表示的最大值多一个约模。如果E1是有符号类型和非负值,并且E1× 2 E2在结果类型中可表示,则这是结果值;否则,行为是未定义的。我不明白在移位的上下文中,当它说**“比结果类型中可表示的最大值多一个模”**时是什么意思。
icomxhvb1#
它基本上是在讨论integer wrapping,如果数学值大于类型的最大可表示值,那么它就进行 Package ,即 modulo arithmetic。
bbmckpt72#
结果类型中可表示的最大值将设置其所有位,而不是2的单次幂。然而,模运算所针对的数字(当值开始换行时)是2的幂,即下一个数字,可以通过将1加到最大可表示值上来获得。
0lvr5msh3#
思考这个问题的一个好方法是查看正在发生的事情的二进制表示。当is声明时,结果的值是E1× 2 E2,比结果类型中可表示的最大值多一个模。让我们使用一个无符号字符,它是一个8位类型,最大值为255
unsigned char ch = UCHAR_MAX // ch : 255 : 1111 1111
现在,让我们将值左移1,并允许我们自己能够超越8位(让我们再添加4位)
ch = ch << 1; // ch : 510 : 0001 1111 1110
我们无法将12位sudo数存储在无符号字符中,因此我们需要保留仍然适用的信息,一种方法是通过UCHAR_MAX + 1进行模约简。您可能会问为什么是UCHAR_MAX + 1,UCHAR_MAX + 1如下所示
UCHAR_MAX // 255 : 1111 1111 UCHAR_MAX + 1 // 256 : 0001 0000 0000
因此,当我们取超出其限制的值并用UCHAR_MAX + 1对其取模时,我们最终会剥离允许的8位值以上的所有二进制数字。
ch % (UCHAR_MAX + 1) // 510 % 256 = 254 // 0001 1111 1110 % 0001 0000 0000 = 1111 1110
提供移位ch << 1的预期结果,这是C将输出的结果。在计算级别,这不会发生,因为我们不能随意超出允许的大小,所以左移1超过最大值会导致回绕,将最低有效位更改为0。我希望这与已经为这个问题提供的其他答案沿着有所帮助!
ch << 1
3条答案
按热度按时间icomxhvb1#
它基本上是在讨论integer wrapping,如果数学值大于类型的最大可表示值,那么它就进行 Package ,即 modulo arithmetic。
bbmckpt72#
结果类型中可表示的最大值将设置其所有位,而不是2的单次幂。然而,模运算所针对的数字(当值开始换行时)是2的幂,即下一个数字,可以通过将1加到最大可表示值上来获得。
0lvr5msh3#
思考这个问题的一个好方法是查看正在发生的事情的二进制表示。
当is声明时,结果的值是E1× 2 E2,比结果类型中可表示的最大值多一个模。
让我们使用一个无符号字符,它是一个8位类型,最大值为255
现在,让我们将值左移1,并允许我们自己能够超越8位(让我们再添加4位)
我们无法将12位sudo数存储在无符号字符中,因此我们需要保留仍然适用的信息,一种方法是通过UCHAR_MAX + 1进行模约简。您可能会问为什么是UCHAR_MAX + 1,UCHAR_MAX + 1如下所示
因此,当我们取超出其限制的值并用UCHAR_MAX + 1对其取模时,我们最终会剥离允许的8位值以上的所有二进制数字。
提供移位
ch << 1
的预期结果,这是C将输出的结果。在计算级别,这不会发生,因为我们不能随意超出允许的大小,所以左移1超过最大值会导致回绕,将最低有效位更改为0。
我希望这与已经为这个问题提供的其他答案沿着有所帮助!