【问题标题】:Weird behaviour in PHP and Apache2: different output in different serversPHP 和 Apache2 中的奇怪行为:不同服务器中的不同输出
【发布时间】:2017-07-14 18:24:37
【问题描述】:

我在 Mac 和 Linux 中运行的 PHP 代码中遇到了不同的输出。

我有 2 台服务器运行以下代码:

    $ltt = ((ord($str[7]) << 24) | (ord($str[8]) << 16) | (ord($str[9]) << 8) | (ord($str[10]))) / 1000000;

即使ord(str[ ]) 的输出也是一样的:

[7] = 254
[8] = 26
[9] = 22 
[10] = 216

但是,在运行 php 5.3.6 的 MAMP 堆栈 (Mac) 上,如果 $ltt 原本应该是负数,则返回 4263.12265(不正确)。

在运行相同 php 版本的 LAMP 堆栈 (Ubuntu) 上,它将返回确切的负值 -31.84465

这只发生在负数的情况下..

更新地址。信息:

  • var 转储给出þØçï_Kstring(25) "þØçï_K"
  • bin2hex 给出000e1b00000000fe1a16d806e707ef0000045f0000004b0000

将函数简化为仅包含数字输入,输出仍然不同

$ltt = (254 << 24 | 26 << 16 |  22 << 8 | 216)/ 1000000;

MAMP 上的4263.12265 和 LAMP 上的-31.84465

【问题讨论】:

  • 两台机器的php配置一样吗?相同的版本并不总是意味着相同的设置;)
  • 一个是 64 位,另一个是 32?我不认为它实际上应该在这里很重要......
  • 两者都是 32 位的,配置是库存的,除了内存限制和 post_Data 的一些变化..
  • echo PHP_INT_SIZE 给你什么?这将有助于消除 32 与 64 的问题。
  • @SalmanA 我在 MAMP 堆栈上得到 '8'

标签: php apache mamp lamp


【解决方案1】:

这是一个 32 位与 64 位的问题。

因为您的最高有效字节 > 127,在 32 位平台上,由于整数溢出,这被解释为负值 - 最高有效位已设置。在 64 位平台上则不然。

解决方案是使用pack()unpack(),这样您就可以指定应该对整数进行签名。 EDIT 修复了这个代码示例见编辑2

$packed = pack('C*', ord($str[7]), ord($str[8]), ord($str[9]), ord($str[10]));
$unpacked = unpack('l', $packed);
$lat = current($unpacked);

...但是您也应该意识到这不适用于小端架构,因为字节顺序将是错误的。您可以简单地颠倒打包字节的顺序来解决这个问题,但我只是想围绕一个无处不在的解决方案。

编辑 2

好的,我花了一些时间来解决这个问题,但我们最终到达了那里:

您需要做的是,如果设置了最高有效位,或者将结果与未设置最低 32 位但其余部分设置的数字相结合。所以以下适用于 32 位和 64 位:

<?php

// The input bytes as ints
$bytes = array(254, 26, 22, 216);

// The operand to OR with at the end
$op = $bytes[0] & 0x80 ? (~0 << 16) << 16 : 0;

// Do the bitwise thang
$lat = (($bytes[0] << 24) | ($bytes[1] << 16) | ($bytes[2] << 8) | $bytes[3]) | $op;

// Convert to float for latitude
$lat /= 1000000;

echo $lat;

【讨论】:

  • @ÁlvaroG.Vicario 我只能肯定地知道这一点,因为我对示例字节进行了数学计算,结果很好。 MAMP 堆栈是 64 位的。但是,我提出的解决方案代码是错误的 :-( 现在正在处理它,但是如果您有解决方案,我很乐意支持它,因为它还很早,而且我的心理二进制计算器还不能正常工作。
  • 感谢您的回答.. 我仍然得到 0 作为输出。
  • @Reddox 参见上面的编辑。实际上不需要检查平台int大小,只检查是否设置了最高有效位。
  • 仅供参考,双倍 &lt;&lt; 16 是因为如果您尝试在 32 位平台上使用 &lt;&lt; 32,PHP 会抛出异常,这经常让我非常恼火。
  • @Reddox 需要注意的重要一点是,这不是特定于 PHP 的。位运算在任何地方的工作方式都是一样的,并且在大多数类 C 语言中它们的语法是相同的。我没有可以指出的具体教程(尽管谷歌搜索“按位教程”会产生大量看起来合理的结果;-))但我一直发现最好的学习方法是实践——我真的掌握了通过在 PHP 中实现 DHCP 服务器,DNS 也是另一个很好的协议选择。如果你不像我那么悲伤,你可能会觉得这有点沉重。
猜你喜欢
  • 2020-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
相关资源
最近更新 更多