前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【临时解决】php int 32 64,关于64位PHP仍然使用32位数字的问题「建议收藏」

【临时解决】php int 32 64,关于64位PHP仍然使用32位数字的问题「建议收藏」

作者头像
全栈程序员站长
发布2022-07-19 12:11:30
7930
发布2022-07-19 12:11:30
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是全栈君。

首先,我们知道有两个常量。PHP_INT_MAX和PHP_INT_SIZE。

根据PHP官方手册所说,整型数的字长和平台有关,尽管通常最大值是大约二十亿(32 位有符号)。64 位平台下的最大值通常是大约 9E18。PHP 不支持无符号整数。Integer 值的字长可以用常量 PHP_INT_SIZE来表示,自 PHP 4.4.0 和 PHP 5.0.5后,最大值可以用常量 PHP_INT_MAX 来表示。

但是,当我们在Windows下使用64位PHP(版本5.6.4和5.2.17)的时候,PHP_INT_SIZE为4,PHP_INT_MAX为2^31-1。与之相反的是,如果在Linux下使用64位PHP,PHP_INT_SIZE为8,PHP_INT_MAX为2^63-1。PHP Bugs官方也有这么一条BUG报告:

https://bugs.php.net/bug.php?id=64863

【临时解决】php int 32 64,关于64位PHP仍然使用32位数字的问题「建议收藏」
【临时解决】php int 32 64,关于64位PHP仍然使用32位数字的问题「建议收藏」

以下是我的输出

代码语言:javascript
复制
D:\Website\IIS>cat int.php

echo 'PHP_VERSION = ' . PHP_VERSION . "\n";

echo 'PHP_INT_MAX = ' . PHP_INT_MAX . "\n";

echo 'PHP_INT_SIZE = ' . PHP_INT_SIZE . "\n";
代码语言:javascript
复制
D:\Website\IIS>php int.php

PHP_VERSION = 5.6.4

PHP_INT_MAX = 2147483647

PHP_INT_SIZE = 4
代码语言:javascript
复制
D:\Website\IIS>php --version

PHP 5.6.4 (cli) (built: Dec 17 2014 13:23:31)

Copyright (c) 1997-2014 The PHP Group

Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies

with Xdebug v2.2.7, Copyright (c) 2002-2015, by Derick Rethans

为什么呢?

还是查代码。

我们可以在PHP的main/main.c中查到

代码语言:javascript
复制
REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);

嗯,那看来和C语言的long长度有关。那应该是编译器的问题了。

我们知道,PHP在Windows下用的VC++编译器。那试试看咯。

先上代码

代码语言:javascript
复制
#include 

using namespace std;

int main() {

cout <

cout <

cout <

return 0;

}

首先是在x86下编译的结果

代码语言:javascript
复制
Z:\>cl /EHsc int.cpp && int

Microsoft (R) C/C++ Optimizing Compiler Version 17.00.60610.1 for x86

Copyright (C) Microsoft Corporation.  All rights reserved.

int.cpp

Microsoft (R) Incremental Linker Version 11.00.60610.1

Copyright (C) Microsoft Corporation.  All rights reserved.

/out:int.exe

int.obj

int (size = 4) max = 2147483647

long (size = 4) max = 2147483647

llong (size = 8) max = 9223372036854775807

再用64位编译器编译吧。

代码语言:javascript
复制
Z:\>cl /EHsc int.cpp && int

Microsoft (R) C/C++ Optimizing Compiler Version 17.00.60610.1 for x64

Copyright (C) Microsoft Corporation.  All rights reserved.

int.cpp

Microsoft (R) Incremental Linker Version 11.00.60610.1

Copyright (C) Microsoft Corporation.  All rights reserved.

/out:int.exe

int.obj

int (size = 4) max = 2147483647

long (size = 4) max = 2147483647

llong (size = 8) max = 9223372036854775807

嗯,很好,我们用g++编译器编译呢?

代码语言:javascript
复制
$ g++ -v

Using built-in specs.

COLLECT_GCC=g++

COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-cygwin/4.8.3/lto-wrapper.exe

Target: x86_64-pc-cygwin

Configured with: /cygdrive/i/szsz/tmpp/cygwin64/gcc/gcc-4.8.3-2/src/gcc-4.8.3/configure --srcdir=/cygdrive/i/szsz/tmpp/c

ygwin64/gcc/gcc-4.8.3-2/src/gcc-4.8.3 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdi

r=/usr/libexec --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --libdir=/usr/lib --datarootdir=/usr/share --

docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=x86_64-pc-cygwin --host=x86_64-pc-cygwin --target

=x86_64-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --enable-shared --enable-shared-libgcc --enable-sta

tic --enable-version-specific-runtime-libs --enable-bootstrap --disable-__cxa_atexit --with-dwarf2 --with-tune=generic -

-enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enabl

e-libgomp --disable-libitm --enable-libquadmath --enable-libquadmath-support --enable-libssp --enable-libada --enable-li

bgcj-sublibs --disable-java-awt --disable-symvers --with-ecj-jar=/usr/share/java/ecj.jar --with-gnu-ld --with-gnu-as --w

ith-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --libexec

dir=/usr/lib

Thread model: posix

gcc version 4.8.3 (GCC)

sx@zsx-pc /cygdrive/z

$ g++ int.cpp -o int & ./int

[1] 25508

int (size = 4) max = 2147483647

long (size = 8) max = 9223372036854775807

llong (size = 8) max = 9223372036854775807

比较一下这两个编译器long的size和max,就能知道为什么在老版本PHP中INT_MAX的值不一样了。

REGISTER_MAIN_LONG_CONSTANT(“PHP_INT_SIZE”, SIZEOF_ZEND_LONG, CONST_PERSISTENT | CONST_CS);

所以,PHP7中,应该不会再出现这个问题了

Windows系统下64位PHP中PHP_INT_MAX为32位

相信很多在Windows环境开发的人都遇到一个问题,就是从数据库里取出的int值比64位PHP里面的int值大,导致用intval过滤之后,数值不准确。

Mysql中int分有符号和无符号,有符合的最大值为:2147483647 ,无符号的最大值为:4294967295。

理论上64位的PHP的PHP_INT_SIZE是:8 ,PHP_INT_MAX是:9223372036854775807。

实际上在Linux系统下64位PHP的PHP_INT_MAX的值是:9223372036854775807 ,但是在Windows系统下输出64位PHP的PHP_INT_MAX的值却是:2147483647。

通过查看PHP源码中PHP_INT_SIZE的定义:

1

REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);

可以看到PHP_INT_SIZE的大小是与C语言的long类型长度一样的

PHP在Windows平台是用VC++编译的,在Linux平台是用g++编译的。查了一下关于这两个编译器在64位环境的资料:

VC++(64位)

g++(64位)

int

4

4

long

4

8

long long

8

8

原来在64位编译环境中VC++和g++的long类型长度是有差别的。所以Windows下64位的PHP的int会比Mysql中无符号的int小。

在不升级php版本的情况下,如何解决这个问题呢?临时改动项目:

代码语言:javascript
复制
在框架中将

return PHP_INT_MAX  > 2147483647;
改为

return PHP_INT_MAX +1 > 2147483647;
【临时解决】php int 32 64,关于64位PHP仍然使用32位数字的问题「建议收藏」
【临时解决】php int 32 64,关于64位PHP仍然使用32位数字的问题「建议收藏」

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/111468.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年2月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Windows系统下64位PHP中PHP_INT_MAX为32位
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档