5

当我运行时,在我的本地机器 bash 中:

echo $((192 << 24))
3221225472

但是在我的嵌入式目标繁忙的盒子 SHELL 上,我得到了其他东西:

echo $((192 << 24))
-1073741824

不过,当我左移一个较小的数字时,它就起作用了。嵌入式设备是 64 位的,我的本地主机是 32 位的。

需要说明的是,在 32 位机器上,该值为正,在 64 位机器上为负。

编辑:这是在带有 SHELL 的 64 位机器的嵌入式设备上。左移 23 时不会发生这种情况。

echo $((192 << 23))
1610612736
echo $((192 << 24))
-1073741824

在本地主机上,这是一台带有 BASH 的 32 机器

echo $((192 << 55))
6917529027641081856
echo $((192 << 56))
-4611686018427387904
4

6 回答 6

3

的二进制表示19211000000。当您将其向左移动 24 位时,唯一设置的两个位是两个最高有效位 - 表示为11000000 00000000 00000000 00000000. 当 32 位系统看到最高有效位集时,它会将其解释为“二进制补码”格式的负数。对于 64 位系统,最高有效位仍然为零,因此它被解释为正数。

这只是 32 位机器上的整数溢出。当使用 32 位和 64 位有符号整数类型时,您可能会期望在 C 或任何其他语言中具有相同的行为。

于 2013-09-19T15:29:51.827 回答
2

POSIX(这里)说“只需要有符号的长整数运算”,而在 C 中,long 至少是 32 位;话虽如此,一些 shell 明确地选择了一个固定的宽度,例如 mksh 使用 32 位算术,并且偷看busybox的源代码(math.h)似乎他们只使用 64 位是 ENABLE_SH_MATH_SUPPORT_64 是#define'd,无论是否底层系统是 32/64 位。如果有人知道更好,请说出来!

于 2013-09-20T14:43:52.143 回答
1

很明显,结果在您的嵌入式设备上溢出。根据您的发现进行的一些计算似乎证实了这一假设

$ echo 3221225472 - 1073741824 | bc -l
2147483648

$ echo 2^31 | bc -l
2147483648

如果你在本地机器上尝试更多,你会发现它也会溢出!

$ echo $((192 << 56))
-4611686018427387904

编辑:正如您评论说您是 Busybox 1.13.2,您有可能遇到问题。升级可能会有所帮助!

于 2013-09-19T15:29:46.717 回答
1

好吧,这仅仅是因为表示数字的位数。192 (0xc0) 移位时变为 0xc0000000。在 32 位机器上,它已经是一个负数,而在 64 位机器上,它仍然在一个正数范围内。

于 2013-09-19T15:30:35.450 回答
1

我想你几乎回答了你自己的问题——32 位机器中的 shell 大概使用 32 位有符号整数来进行这种算术,而 64 位机器中的 shell 大概使用 64 位有符号整数。对于 32 位有符号整数,最大可能值为 2^31,因此 3221225472 会导致溢出。

于 2013-09-19T15:31:59.053 回答
1

在我的本机嵌入式 android shell 上得到了同样的结果,但是在启动 busybox shell 后它可以正常工作。

# echo $((192 << 23))
1610612736
# echo $((192 << 23))
1610612736
# echo $((192 << 24))
-1073741824

# busybox sh
/ # echo $((192 << 23))
1610612736
/ # echo $((192 << 24))
3221225472
/ # busybox

使用 BusyBox v1.19.3

于 2016-04-26T08:52:37.267 回答