最近帮公司面试PHP程序员,碰到一个奇怪的现象:一个简单的,只有两行代码的面试题,竟然80%的人都不知道其正确的结果。
面试题如下:
让说出最终var_dump()打印的结果。我得最多的答案是:输出一个数组,即:array(‘zhangsan’)。他们认为,把一个 字符串 当作数组使用时,会把这个变量转换为一个数组类型,从而得到这个结果。
你觉得呢?
说实话,在听到他们给出这个答案的时候,我表示很不理解。我想再怎么错误也不应该是这个答案呀,给指针下的某个下标进行赋值,会改变当前指针所指的变量类型?
为弄清楚正确答案,下面我们要对这几行代码抽丝剥茧,逐行说明。
首先,第一行代码完全没有异议,是把字符串“ilove”赋给了变量$str。
这一行不是很复杂,真正复杂、饱含细节的在于第二行代码。
但在开始做题之前,需要回顾一些PHP的基本知识。虽然说是基本,但我却非常惊讶很多开发同学居然对此都了解不多,或者说看过但没记住或者理解,甚至完全没去接触过。
PHP基本数据类型
要想得知最终正确的答案,需要对PHP字符串和数组有较为深刻的理解,对PHP基本数据类型和变量的底层知识有一定的认识。
根据PHP官方文档,PHP基本数据类型有:
-
Boolean 布尔类型、
-
integer 整型、
-
Float 浮点型、
-
String 字符串、
-
Array 数组、
-
Object 对象、
-
Resource 资源类型、
-
NULL
-
Callback / Callable 类型
PHP数组
PHP数组的实现实际上是通过hash表来实现的,理解了这一数据结构后,再来理解它所提供的操作就顺理成章了。PHP数组里面的知识很多,但这里只说一个点:PHP数组的下标。
先来简单看下这份额外的代码:
问:最后字母E对应的数组下标是多少?为什么?
不少同学,在回答这个问题时也卡住了,因为不知道PHP数组的下标的规则。上面的问题回答不出来,对我们的面试题影响不大。但接下来的这个问题就非常关键了:PHP数组的下标有哪些类型?如果这一点不清楚,那么会对很多PHP的函数和操作,都理解得不够透彻深刻。
其实,这些重要的信息在PHP官方文档上都有记载,但在平时学习PHP过程中,很多人都是觉得看这些“又长又臭”的文档没意思,而且花时间,宁愿去网上搜索所谓的快速入门教程,但这些教程往往也是PHP开发新手编写的,他们虽然解决了问题,但很可能他们也是理解未全面,或者说明不够全面。简单来说,一切资料,都应从官方文档上寻求参考。
在PHP官方文档里,PHP数组的下标有两种类型:一种是整数,一种是字符串。如下:
PHP 数组可以同时含有 integer 和 string 类型的键名,因为 PHP 实际并不区分索引数组和关联数组。如果对给出的值没有指定键名,则取当前最大的整数索引值,而新的键名将是该值加一。如果指定的键名已经有了值,则该值会被覆盖。
因此,上面额外代码中字母E在数组中,对应的下标为2,如下图所示。
PHP数组与字符串的异同
PHP数组与PHP字符串有什么不同,又有什么相同之处呢?
很多同学都知道数组与字符串的区别,但实际上它们也是有相同之处的。如果这样说比较抽象,我们可以通过一些示例来理解。如下:
上图所示的代码,最后的结果是什么呢?
很多语言,包括C/C++, Java 等,以及PHP,字符串其实也是一个有序的序列。不同的是,不同语言底层实现方式会有差异。例如C语言中,要在字符串最后加一个结束符’\0’,不然就会导致内存问题;Java语言的字符串则是缓冲区的不变值;而PHP字符串也可以当作是一个数组的形式。
由此,可以得知上面的代码,最后输出的结果为:$str[0] == ‘z’,$str[1] == ‘h’,$str[10]由于下标10不存在,因此会出现Notice并输出空。如下:
铺垫了那么多,其实是为了说明,某种情况下,PHP的字符串也可以当作数组来使用。
回到面试题,先看左边,尝试解释一下第二行代码背后发生的事情。
按照PHP语言的解析机制,执行的顺序是先执行等号左边的代码,再到右边的表达式。所以,先来看等号左边部分发生了什么事情。
任何问题的处理,都离不开它的上下文。乍一看这样的代码是没问题的,但关键是,第二行的$str不是一个字符串,而是一个数组。前面我们已经知道:
-
PHP字符串也可以通过下标来操作,但实际有效下标只能是0、1、2这样的数字位置
-
PHP数组下标有两种类型,可以是整数或者字符串
那么,对于一个字符串变量,给定一个字符串的下标?这意味着什么呢?PHP又是如何处理的呢?
显然,这个字符串不会因此而变成一个数组,它还是一个字符串。但由于当字符串被当作数组来使用时,其下标只能是整型(如,0,1,2……),因此,如果其访问下标为字符串,PHP会进行隐式类型转换,即把字符串下标转成整型下标。
那怎么将字符串下标转换成整型下标呢?
PHP字符串转整型的规则
PHP字符串怎么转成整型?快速问一个PHP开发人员,他都可以告诉你,可以这样做:使用intval()函数,或者前面加个(int)。那好,你继续问他,以下这些代码,结果是什么?
这时,就不一定能完全回答出来了。知道PHP的函数怎么用是一回事,知道为什么结果是这样又是一回事。理解背后的规则更为重要。
PHP官方文档里面说,当一个字符串被当作一个数值来取值,其结果和类型如下:
-
如果该字符串没有包含 ‘.’,’e’ 或 ‘E’ 并且其数字值在整型的范围之内(由 PHP_INT_MAX所定义),该字符串将被当成 integer 来取值。其它所有情况下都被作为 float 来取值。
-
该字符串的开始部分决定了它的值。如果该字符串以合法的数值开始,则使用该数值。否则其值为 0(零)。合法数值由可选的正负号,后面跟着一个或多个数字(可能有小数点),再跟着可选的指数部分。指数部分由 ‘e’ 或 ‘E’ 后面跟着一个或多个数字构成。
因此,上面代码最后输出结果应该如下:
再回到面试题。通过上面的介绍,我们知道,当一个字符串被当作数组来使用时,其下标如果不是整型,PHP会强制将其转换成整型。因此,$str[‘name’]中的name会被强制转换成整型0。由此面试题可以等价于如下形式:
到这里,我们已经知道,第二行代码,实际上是把字符串的第一个位置(下标为0)进行赋值,所以最后它不会变成数组类型,依然是字符串。
数组又是怎么转换成字符串的呢?当然,这里就不再展开细讲,因为大家已经熟悉。数组转成字符串,会变成“Array”这样的字样。如下:
由此,我们的面试题可以进一步简化为如下形式:
由于原来的$str[0]只能保存一个字符,因此,字符串Array不可能全部保存到下标为0的位置。实际上,PHP会自动获取Array的第一个位置,即A,然后,再来进行赋值操作。
到此,我们就不难得出面试题最后的结果为:Alove。如下:
总结
这道面试题,看起来虽然简单,但关联的知识点非常多,考察面非常广。可用于评估开发同学对于PHP语言的把握程度。
相关文章
本站已关闭游客评论,请登录或者注册后再评论吧~