32 至 64 位“陷阱” 在 PHP 中

发布于 2024-07-11 02:38:54 字数 239 浏览 5 评论 0原文

上周末我为我的网站更改了虚拟主机。 我所在的主机服务器是 32 位操作系统,而我迁移到的主机服务器是 64 位操作系统。 出乎意料的是,我的一些 PHP 脚本开始给出不正确的结果。

就我而言,<< 和>> (位移位)操作是罪魁祸首。 我最终不得不用 0xFFFFFFFF 屏蔽结果,然后更改结果(如果结果为负)才能像以前一样工作。

我的 PHP 脚本中是否还有其他可能存在的问题?

Last weekend I changed webhosts for my website. The host server I was on was a 32-bit OS and the one I moved to is 64-bit. Unexpectedly, some of my PHP scripts started giving incorrect results.

In my case the << and >> (bit shift) operations were the culprit. I ended up having to mask the result with 0xFFFFFFFF and then changing the result if negative for it to work as it did before.

Are there any other possible problems in my PHP scripts I should look for?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

好多鱼好多余 2024-07-18 02:38:54

它是一种高级语言,因此任何与位无关的内容(按位运算符、位移位)都是相同的。

It's a high level language, so anything non-bit related (bitwise operators, bitshift) will be the same.

丢了幸福的猪 2024-07-18 02:38:54

整数可以是 64 位而不是 32 位。 有一些奇怪的案例这可能会导致问题。

An integer may be 64bit instead of 32bit. There are some bizarre cases where this may cause problems.

一张白纸 2024-07-18 02:38:54

位操作需要特别小心才能在系统/体系结构之间进行移植。

在C中,<< 和>> 通过使用无符号变量可以使操作变得可移植,这消除了负数的一/二补码规则。

作为一般规则,不要使用固定长度掩码进行位操作(如 & 和 |)。 这些是依赖于架构的。

例如。 重置最后 4 位:
掩码 0xF0 将在 8 位上工作
架构,但不是 16 位。 结果会有所不同(16 位可能设置了未包含在掩码中的其他位)。

要解决此问题,请使用 ~ 运算符。 掩码 ~0xF 相当于 0xF0,但适用于任何架构。 除最后 4 位之外的所有位都将被重置

bit manipulation requires special care to make portable between systems/architectures.

In C, << and >> operations can be made portable by using unsigned variables, which removes the ones/twos compliment rules for negative numbers.

As a general rule, dont use fixed-length masks for bit manipulation (like & and |). These are architecture dependent.

Eg. Resetting the last 4 bits: the
mask 0xF0 will work on an 8-bit
architecture, but not 16-bit. The results will be different (16-bit may have other bits that are set that are not included in the mask).

To overcome this problem, make use of the ~ operator. The mask ~0xF is equivalent to 0xF0, but will work on any architecture. All bits except the last 4 will be reset

时间你老了 2024-07-18 02:38:54

strtotime 在 64 位上的行为有所不同。 来自 PHP.net:

注意:

时间戳的有效范围通常是从 1901 年 12 月 13 日星期五 20:45:54 UTC 到 2038 年 1 月 19 日星期二 03:14:07 UTC。 (这些日期对应于 32 位有符号整数的最小值和最大值。)此外,并非所有平台都支持负时间戳,因此您的日期范围可能会被限制为不早于 Unix 纪元。 这意味着 1970 年 1 月 1 日之前的日期将无法在 Windows、某些 Linux 发行版和其他一些操作系统上运行。 PHP 5.1.0 和更新版本克服了这个限制。

对于 64 位版本的 PHP,时间戳的有效范围实际上是无限的,因为 64 位可以代表任一方向的大约 2930 亿年。

我们的代码正在执行 strtotime('0000-00-00') 并预期结果为 false,当我们转移到 64 位时,我们返回一个负整数。

strtotime behaves differently on 64 bit. From PHP.net:

Note:

The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC. (These are the dates that correspond to the minimum and maximum values for a 32-bit signed integer.) Additionally, not all platforms support negative timestamps, therefore your date range may be limited to no earlier than the Unix epoch. This means that e.g. dates prior to Jan 1, 1970 will not work on Windows, some Linux distributions, and a few other operating systems. PHP 5.1.0 and newer versions overcome this limitation though.

For 64-bit versions of PHP, the valid range of a timestamp is effectively infinite, as 64 bits can represent approximately 293 billion years in either direction.

We had code that was doing strtotime('0000-00-00') and expected the result to be false, when we moved to 64 bit we got back a negative integer.

愛上了 2024-07-18 02:38:54

您会看到的唯一问题是当您依赖数据的 32 位二进制表示形式时。
主要是因为 PHP 使用有符号整数,当使用 (int)、numbers > 显式转换为 int 时,您会看到哈希、密钥生成等方面的问题。 2^32 将换行,因为它们不会在 64 位环境中换行,除非它们 > 当然是2^64。

4 与 8 位示例:

十进制值问题:

     0010 >> 1 =      0001   [ 1 dec ]
0000 0010 >> 1 = 0000 0001   [ 1 dec ]

它们都会产生相同的结果(十进制),但是:

     0100 << 1 =      1000   [ -8 dec ]
0000 0100 << 1 = 0000 1000   [ 16 dec ]

换行问题:

     1000 << 1 =      0000   [  0 dec ]
0000 1000 << 1 = 0001 0000   [ 32 dec ]

所有整数/浮点运算将被视为 64 位值,因此如果您的最终结果依赖于 32 位块您将必须对此进行补偿。

Only problem's you'll see are when you relied on 32-bit binary representation of data.
Mainly because PHP uses signed integers, you'll see issues in Hashing, key generation, etc... when explicitly casting to int with (int), numbers > 2^32 will wrap where as they will not wrap in a 64 bit environment unless they are > 2^64 of course.

4 vs 8 bit example:

Decimal value issues:

     0010 >> 1 =      0001   [ 1 dec ]
0000 0010 >> 1 = 0000 0001   [ 1 dec ]

These both produce the same result (decimal wise), however:

     0100 << 1 =      1000   [ -8 dec ]
0000 0100 << 1 = 0000 1000   [ 16 dec ]

Wrapping issues:

     1000 << 1 =      0000   [  0 dec ]
0000 1000 << 1 = 0001 0000   [ 32 dec ]

All integer/floating point ops will be treated as 64-bit values, so if your end result relies on 32bit chunks you will have to compensate for such.

芸娘子的小脾气 2024-07-18 02:38:54

浮点除法的结果会因为增加到64位而受到影响; 因此,如果您的代码做了一些愚蠢的事情,例如将浮点除法的结果与硬编码常量进行比较,那么它就会崩溃。

The results of floating point division will be affected by the increase to 64-bits; so if you have code that does something stupid like comparing the results of floating point division to hardcoded constants, expect it to break.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文