PHP是弱类型语言,就像JavaScript一样,在定义变量时,不需要强制指定变量的类型。同时,PHP又有着强大的数组功能,数组的Key即可以是普通的数字类型下标,也可以是字符串类型的Hash键值,那么,当一个数组的Key同时拥有字符串和数字时,会产生什么情况呢?

首先来看下面这样一段代码:


$arr = [
"1" => "a",
"01" => "b",
1 => "aa",
1.1 => "aaa",
"0.1" => "bb",
]; var_dump($arr); // array(3) {
// [1] =>
// string(3) "aaa"
// '01' =>
// string(1) "b"
// '0.1' =>
// string(2) "bb"
// }

咦?我们定义的"1"、1下标的值都变成了1.1的"aaa"了?

没错,PHP中的数组Key值只接受数字和字符串类型,当Key是字符串时,会强强制转换为数字类型,遵守类型强制转换的规则。浮点数也是同样的道理,直接转换成了向下取整的整型。

那么"0.1"和"01"为什么还在?首先,"01"不是标准的十进制数值,无法转换成整型,所以"01"还是一个字符串下标,那"0.1"呢?它当然也不是一个标准的十进制数值。这里是违背了字符串转型数字的强制类型转换原则的,在变量的强制转换中,这两种字符串都会被转换为0,但在数组中则不会,这里会是一个坑,也是需要注意的地方。

在PHP官方文档中给出的Key值转换说明如下:

  • 包含有合法整型值的字符串会被转换为整型。例如键名 "8" 实际会被储存为 8。但是 "08" 则不会强制转换,因为其不是一个合法的十进制数值。
  • 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
  • 布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
  • Null 会被转换为空字符串,即键名 null 实际会被储存为 ""。
  • 数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type。

接下来,是笔者曾经做过的一道面试题,和这个类型转换有着非常大的关系,代码如下:


$a = ['a'];
$a[2] = 'b';
$a[] = 'c';
$a['1'] = 'd'; // 以下循环的输出结果是?
foreach ($a as $v) {
echo $v, ',';
} // 以下循环的输出结果是?
for ($i = 0; $i < count($a); ++$i) {
echo $a[$i], ' ,';
}

大家先不要运行,直接看代码看看能不能看出这两段代码的输出结果会是什么,然后运行一下,看看结果和你想像的是不是一样。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/201910/source/%E5%85%B3%E4%BA%8EPHP%E6%95%B0%E7%BB%84Key%E7%9A%84%E5%BC%BA%E5%88%B6%E8%BD%AC%E6%8D%A2.php

参考资料:

https://www.php.net/manual/zh/language.types.array.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

关于PHP数组Key的强制类型转换的更多相关文章

  1. 《You dont know JS》强制类型转换

    强制类型转换 将值从一种类型转换为另一种类型通常称为类型转换,这是显式的情况.隐式的情况被称为强制类型转换 在书中,作者还提出一种区分方式: 类型转换发生在静态类型语言的编译阶段,强制类型转换发生在动 ...

  2. javascript的强制类型转换

    1.toString (1)调用toString方法 Array是将数组中的每个元素字符串化,并使用逗号拼接起来 object返回的是内部属性[[Class]]的值,[object Object] n ...

  3. Js里面的强制类型转换

    js 和 PHP语言一样是弱类型语言.近期我也在看C语言,并没有传说中那么难,既是书中一再强调的指针部分,也没有那么夸张.至少是理论和语法理解起来不是很难.看起来凡是什么东西,不要总是被别人的话迷惑了 ...

  4. 数据类型/强制类型转换 和运算符---标识符规则/关键字 a++和++a区别

    3.2关键字都是小写,TRUE FALSE NULL都不是Java关键字 3.3数据类型 变量相当于一个有名称的容器,该容器用于装各种不同类型的数据 Java类型分为2种 基本类型: 引用类型: 基本 ...

  5. c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast

    c++强制类型转换:dynamic_cast.const_cast .static_cast.reinterpret_cast 博客分类: C/C++ CC++C#编程数据结构  dynamic_ca ...

  6. C++开发必看 四种强制类型转换的总结 [转]

    一.C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:     TYPE b = (TYPE)a 二.C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. co ...

  7. C++四种强制类型转换关键字

    C语言使用强制类型转换(Type Cast)很简单,不管什么类型的转换,形式都如下: TYPE b = (TYPE)a; c++提供了4种类型转换操作符来应对不同场合的应用. const_cast   ...

  8. C++开发必看 四种强制类型转换的总结

    C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. const_cast ...

  9. C语言结构体的强制类型转换

    陈浩师兄03年的一篇博客<用C写有面向对象特点的程序>描述了用C语言来实现类似C++类继承的方法,这样方法的核心要点就是结构体的强制类型转换,让我来简单分析分析C语言中的结构体强制类型转换 ...

随机推荐

  1. wait_time参数

    1.未修改的 wait_timeout 的初始值是28800,单位为秒,等于8个小时 2.wait_timeout过大有弊端,其体现就是mysql里有大量的sleep进程无法及时释放,拖累系统性能 但 ...

  2. 【笔记】初探KNN算法(1)

    KNN算法(1) 全称是K Nearest Neighbors k近邻算法: 思想简单 需要的数学知识很少 效果不错 可以解释机器学习算法使用过程中的很多细节问题 更加完整的刻画机器学习应用的流程 其 ...

  3. JunAMS v1.2.1.20190403代码审计笔记

    前言 CNVD-2020-24741 过程 JunAMS是以ThinkPHP为框架的开源内容管理系统,本地搭建受影响版本JunAMS v1.2.1.20190403 前台没有上传功能,进入后台.发现在 ...

  4. 谈谈ARM运行C程序的内部机制

    文章目录 一.代码 二.知识储备 1.ARM汇编指令 2.寄存器知识 三.代码解析 1.指令分析 第一条指令: 第二条指令: 第三条指令: 第四条指令: 第五.六条指令: 第七条指令: 第八.九.十条 ...

  5. Java中Lambda表达式基础及使用详解

    概述 Lambda 是JDK 8 的重要新特性.它允许把函数作为一个方法的参数(函数作为参数传递进方法中),使用 Lambda 表达式可以使代码变的更加简洁紧凑,使Java代码更加优雅. 标准格式 三 ...

  6. 题解 a

    传送门 和入阵曲那题很像 这里 \(n\) 很小,可以直接 \(n^2\) 压成一维考虑 然后就是对每个 \(j\) 查询 \([j-r, j-l]\) 中数的个数 这里我是用树状数组求的,带个log ...

  7. 并发容器之ConcurrentHashMap

    JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都 串行化了,这样保证了线程的安全性,所以这种方法的代价就是严重降低 ...

  8. 三、vue前后端交互(轻松入门vue)

    轻松入门vue系列 Vue前后端交互 六.Vue前后端交互 1. 前后端交互模式 2. Promise的相关概念和用法 Promise基本用法 then参数中的函数返回值 基于Promise处理多个A ...

  9. ArcGIS图层添加字段出现:“定义了过多字段”

    首先,我图层数据格式为mdb,也就是Access数据库 Access一个表最大支持255个字段,可是我的才添加第一个字段就出现"定义了过多字段"的错误 打开ArcMap添加字段也是 ...

  10. js之window对象(慕课网学习笔记)

    javaScript定义了一个变量一个函数都会变成window中的一个成员 var a=1; alert(window.a) //会输出a的值 window基础 创建窗口.调整窗口.移动窗口.关闭窗口 ...