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

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

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

首先,我们知道有两个常量。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位数字的问题「建议收藏」 

以下是我的输出

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";
D:\Website\IIS>php int.php

PHP_VERSION = 5.6.4

PHP_INT_MAX = 2147483647

PHP_INT_SIZE = 4
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中查到

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

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

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

先上代码

#include 

using namespace std;

int main() {

cout <

cout <

cout <

return 0;

}

首先是在x86下编译的结果

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位编译器编译吧。

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++编译器编译呢?

$ 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版本的情况下,如何解决这个问题呢?临时改动项目:

在框架中将

return PHP_INT_MAX  > 2147483647;
改为

return PHP_INT_MAX +1 > 2147483647;

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • EnterpriseLibrary 6.0(微软企业库6.0学习笔记) 之Data Access Block 配置和获取链接字符串

    EnterpriseLibrary 6.0(微软企业库6.0学习笔记) 之Data Access Block 配置和获取链接字符串EnterpriseLibrary的特点是快速开发,融合了微软工程师多年的经验,现在在微软内部有专门的一个小组在完善EnterpriseLibray,最近的更新时间是April2013。相关链接

    2022年7月2日
    28
  • windowsform和wpf(winform和wpf我选哪个)

    WPF开发于WinForm之后,从技术发展的角度,WPF比WinForm先进是不容置疑的。我觉得WPF相比于WinForm有下面的一些较好的特性:解决WindowHandle问题在WindowsGDI或WinForm开发中复杂的GUI应用程序,会使用的大量的控件,如Grid等。而每个控件或Gridcell都是一个小窗口,会使用一个Windowhandle,尽管控件厂商提供了很多优化…

    2022年4月12日
    39
  • 数据库系统原理及MySQL应用教程_三十讲之第三讲读后感

    数据库系统原理及MySQL应用教程_三十讲之第三讲读后感此文为极客时间MySQL实战45讲第13节的笔记一、表数据的存放位置表数据既可以存在共享表空间里,也可以是单独的文件。这个行为是由参数innodb_file_per_table控制的:OFF

    2022年8月16日
    8
  • JDBC_3 数据库事物

    JDBC_3 数据库事物数据库事务数据一旦提交,就不可回滚那些操作会导致数据的自动提交?DDL操作一旦执行,都会自动提交-. set autocommit = false不起作用DML默认情况下,一旦执行就会自动提交-. 可以设置set autocommit = false关闭连接的时候会自动提交 Connection connection = DriverManager.getConnection(url, user, password); connection.setAutoCommit

    2022年8月8日
    8
  • javaclasscastexception Scala_java unchecked cast object to T

    javaclasscastexception Scala_java unchecked cast object to T在处理JSON时将一个JSONArray强转成List,在线上环境运行正常,但是换了一个环境就出现ClassCastException这个异常。编译时这个强转不会报错,但是运行时却可能出现异常。所以在对对象进行强制转换的时候一定要加以小心,想好实际的对象类型是什么,可不可以强转。

    2025年8月28日
    5
  • rpc接口测试方法_rpc服务接口测试

    rpc接口测试方法_rpc服务接口测试一、项目需求开发文档已明确要压测的接口是rpc接口,并给出了rpc接口和依赖,如下:RPC接口:<dependency><groupId>com.xueqiu.snowflake</groupId><artifactId>usercenter-client</artifactId><version>2.13.5</version></dependency>调用示例:List&

    2022年10月13日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号