文章目录
参考
环境
项目 | 描述 |
---|---|
PHP | 5.5.0 、5.6.8 、7.0.0 、7.2.5 、7.4.9 、8.0.0 、8.2.9 |
intval()
主角登场
在 PHP 中,intval()
函数用于将其他类型的数据转化为整型数据。
intval(mixed $value, int $base = 10): int
其中:
项目 | 描述 |
---|---|
$value | 需要使用 intval() 进行转化的数据,该参数的值可以是一个整型数值,但转化结果与原数据不会存在任何区别(由该函数的功能决定)。 |
$base | 指定被转化数据 $value 采用的进制(默认为十进制),intval() 将据此解析 $value 并将其转化为 十进制整型数值 。 |
截断而非四舍五入
intval()
函数将 浮点数(含有小数点的数值)
转化为 整数数值
的方式是以小数点为基准将浮点数分为两部分,原浮点数的整数部分即为转化结果
。对此,请参考如下示例:
var_dump(intval('948.53975'));var_dump(intval(0.454397));
执行效果
int(948)int(0)
进制转化
intval()
函数的 $base
参数仅在 $value
参数的数据类型为 字符串
时生效。因此,当你需要将一个 采用 $base 进制的数值
转化为 十进制数值
时,需要 先将该数值转化为字符串
再交由 intval()
函数进行处理。
# 尝试将八进制数值 36363.33, 8 转化为十进制整数值var_dump(intval(36363.33, 8));# 尝试将字符串(包含八进制数值) 36363.33 转化为十进制整数值var_dump(intval('36363.33', 8));
执行效果
int(36363)int(15603)
字符串解析规则
十进制字符串
当 $base
参数的值为默认值 10
时且 $value
参数的值为字符串类型的数据时,intval()
函数的解析规则如下:
- 若字符串的
首个字符不为数字且不为空格等空白字符
,则将该字符串转化为零。 - 若字符串的
首个字符不为数字但为空格等空白字符
,则尝试读取其余字符,忽略遇到到数字字符前的所有空白字符,在遇到非数字字符时停止对字符串的读取并将已读取字符转化为数值
。 - 若字符串的
首个字符为数字
,则尝试读取其余字符,在遇到非数字字符(除符合科学计数法格式的字符 e 或 E外)时停止对字符串的读取并将已读取字符转化为数值
。
举个栗子
var_dump(intval(' 457.935HELLO'));var_dump(intval('Hello45995'));var_dump(intval(' 0000053.0494 '));var_dump(intval('0x2f'));var_dump(intval('0b10101'));
执行效果
int(457)int(0)int(53)int(0)int(0)
其他进制
当 intval()
函数的 $base
参数的值不为默认值且 $value
的数据类型为字符串时,intval()
的解析规则以十进制字符串的解析规则为基础,正常解析其他进制下的特有数字字符(十六进制数包含 a
、b
、c
等特有数字字符)及前缀(如以 0x
或 0X
为前缀的数值常用于表示十六进制数)。 对此,请参考如下示例:
# 十六进制字符串var_dump(intval(' 0X2FHELLO', 16));var_dump(intval('00000x2FHELLO', 16));var_dump(intval('2FHELLO', 16));var_dump(intval('0x18', 16));# 十进制字符串var_dump(intval('0x18'));# 二进制字符串var_dump(intval('0b03940', 2));var_dump(intval(' 0B1010101', 2));var_dump(intval('H010101', 2));var_dump(intval('1010101', 2));
执行效果
int(47)int(0)int(47)int(24)int(0)int(0)int(85)int(0)int(85)
注:
在使用 intval()
处理其他进制的字符串时,需要注意到字符串中的 数值部分
是否以相对应的前缀开头。十六进制数值以 0x
或 0X
为前缀,而不是 0000X
、70x
等。
var_dump(intval('0x2b', 16));var_dump(intval('0000x2b', 16));var_dump(intval(' 0X2B', 16));var_dump(intval('0b10011', 2));var_dump(intval('0000B10011', 2));var_dump(intval(' 0B10011', 2));
执行效果
int(43)int(0)int(43)int(19)int(0)int(19)
科学计数法
e/E 表示法
在 PHP 中,e
与 E
均表示 科学计数法(Scientific Notation)
。科学计数法由 基数
和 指数
两部分组成,常用于
表示非常大或非常小的数值。
在科学计数法中,基数 通常
是一个浮点数,介于 1
到 10
之间,而指数是一个整数,表示要将基数乘以 10
的多少次方。基数与指数之间以字符 e
或 E
进行分隔。
举个栗子
# 1 * 10 ^ 2var_dump(intval('1E2'));# 3.688 * 10 ^ 2var_dump(intval('3.688e2'));# 9999 * 10 ^ -3var_dump(intval(9999E-3));
执行效果
上述示例在 PHP8.0.0
中执行,得到结果如下:
int(100)int(368)int(9)
intval() 在 PHP 不同版本中的表现差异
PHP7.2.5 版本及以上
intval()
在 PHP7.2.5 及以上版本
中的表现符合预期,与我们对科学计数法的认知相符。
PHP7.2.5 版本以下
intval() 函数
在 PHP7.2.5 以下的某个版本以前(仅测试了 PHP7.2.5 与 PHP7.0.0,PHP7.0.0 中,intval() 的表现存在异常,而在 PHP7.2.5 则表现正常。)
表现异常,intval()
的异常行为具体如下:
var_dump(intval('1E2'));var_dump(intval(1E2));var_dump(intval('3.688e2'));var_dump(intval(3.688e2));var_dump(intval('9999E-3'));var_dump(intval(9999E-3));
执行效果
int(1)int(100)int(3)int(368)int(9999)int(9)
在 PHP7.2.5 以下的某个版本
以前,intval()
函数无法正确解析字符 E
或 e
,于是 intval
在解析到 E
或 e
时立即停止,这导致科学计数法实际并未生效。
[WUSTCTF 2020]朴实无华
可能性分析
在 2020
年举办的 CTF 比赛 WUSTCTF
中存在一道名为 朴实无华
的 WEB
题,其中存在这么一段代码:
if(intval($num) < 2020 && intval($num + 1) > 2021){echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.";}else{die("金钱解决不了穷人的本质问题");}
我们需要传递一个 字符串
作为 $num
的值使得判断语句成立以 使得程序继续进行
,而不是因为 die() 函数
的执行而停止。
从逻辑上来说,没有一个数值(字符串形式)可以使得 $num
满足判断语句。但请不要忘记,intval()
在某些 PHP 版本中 对使用科学计数法的数值(字符串)无法正常解析
,这也就产生了绕过的可能。
绕过
$num
在第二个 intval()
函数中以 表达式
的形式出现,字符串在与数值进行运算时,PHP 会将字符串转化为数值
。使用科学计数法的数值(字符串)
在某些版本中无法被 intval() 正确解析
,但 PHP 是认得它的,在与数值 1
进行加法运算时,$num
将被 PHP
正确解析。于是,我们尝试将 $num="1e4"
。对此,请参考如下示例:
$num = '1e4';if(intval($num) < 2020 && intval($num + 1) > 2021){ echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.";}else{ die("金钱解决不了穷人的本质问题");}# 测试print("\n");var_dump(intval($num));var_dump(intval($num + 1));
执行效果
尝试在 PHP7.0.0
版本下执行上述代码,得到如下结果:
我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>int(1)int(10001)
来源地址:https://blog.csdn.net/qq_44879989/article/details/133418606