• 【临时解决】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

     

    以下是我的输出

    D:WebsiteIIS>cat int.php
    
    echo 'PHP_VERSION = ' . PHP_VERSION . "
    ";
    
    echo 'PHP_INT_MAX = ' . PHP_INT_MAX . "
    ";
    
    echo 'PHP_INT_SIZE = ' . PHP_INT_SIZE . "
    ";
    D:WebsiteIIS>php int.php
    
    PHP_VERSION = 5.6.4
    
    PHP_INT_MAX = 2147483647
    
    PHP_INT_SIZE = 4
    D:WebsiteIIS>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位)
    int44
    long48
    long long88

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

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

    在框架中将
    
    return PHP_INT_MAX  > 2147483647;
    改为
    
    return PHP_INT_MAX +1 > 2147483647;

    赞赏码

    非学,无以致疑;非问,无以广识

  • 相关阅读:
    项目风险软考之软工基础知识(1)
    序列输出ZOJ1108 FatMouse's Speed
    电平波特率UART自适应波特率的设置方法
    nullnull2013金山西山居创意游戏程序挑战赛——初赛(3)生日猜猜猜
    删除监听oracle单库彻底删除干净的方法
    类关闭由一个activity启动第二个activity
    代码文件android:向手机卡上写入文件时总是不成功,解决办法
    功能应用程序延迟发送:4款定时发送短信的应用程序
    监听事件android activity中键盘的监听
    nullnull爆笑百家讲坛之十大逆袭情侣.
  • 原文地址:https://www.cnblogs.com/lxwphp/p/15452494.html
Copyright © 2020-2023  润新知