C左移运算中的模行为

8xiog9wr  于 2023-03-12  发布在  其他
关注(0)|答案(3)|浏览(90)

按位移位运算符的ISO C99标准对左移有如下说明:
E1〈〈E2的结果是E1左移E2比特位置;空出的位用零填充。如果E1是无符号类型,则结果的值为E1× 2 E2,比结果类型中可表示的最大值多一个约模。如果E1是有符号类型和非负值,并且E1× 2 E2在结果类型中可表示,则这是结果值;否则,行为是未定义的。
我不明白在移位的上下文中,当它说**“比结果类型中可表示的最大值多一个模”**时是什么意思。

icomxhvb

icomxhvb1#

它基本上是在讨论integer wrapping,如果数学值大于类型的最大可表示值,那么它就进行 Package ,即 modulo arithmetic

bbmckpt7

bbmckpt72#

结果类型中可表示的最大值将设置其所有位,而不是2的单次幂。然而,模运算所针对的数字(当值开始换行时)是2的幂,即下一个数字,可以通过将1加到最大可表示值上来获得。

0lvr5msh

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。
我希望这与已经为这个问题提供的其他答案沿着有所帮助!

相关问题