PHP中的类型:不要担心,要快乐

时间:2021-12-24 14:46:24
PHP中的类型:不要担心,要快乐
所有的编程语言都有某种类型的系统,它规定了不同的类型值可以出现在程序中。这些不同类型通常对应于计算机存储器中的不同位级表示,但是在许多情况下,程序员绝对不必考虑(或者能够混乱)位表示。
PHP的类型系统简单,流线化,灵活,它使程序员与低级细节绝缘。 PHP使得很容易不必担心过多地键入变量和值,因为它不需要输入变量,也因为它处理了很多类型转换。
没有变量类型声明
变量的类型不需要提前声明。
相反,程序员可以直接跳转到赋值,让PHP来处理分配的表达式的类型:
$ first_number = 55.5;
$ second_number =“不是一个数字”;
自动类型转换
PHP很好地在必要时自动转换类型。像大多数其他现代编程语言一样,PHP将做正确的事情,例如,对混合数值类型进行数学运算。表达式的结果
$ pi = 3 + 0.14159
是一个浮点数(双精度数),整数3被简单地转换为浮点数
然后进行添加。
由上下文分配的类型
PHP比大多数语言在执行自动类型转换方面更进一步。考虑:
$ sub = substr(12345,2,2);
print(“sub is $ sub <BR>”);
substrfunction被设计为接受一个字符串作为其第一个输入并返回a
子字符串,起始点和长度由后两个输入确定
功能。而不是递交一个字符串的函数,但是,我们给它的整数12345.会发生什么?事实证明,没有错误,我们得到浏览器的输出:
sub是34
因为substrexpective一个字符串而不是一个整数,PHP转换数字
12345转换为字符串'12345',该字符串替换切片和切块。
由于这种自动类型转换,很难说服PHP给出类型错误 - 事实上,PHP程序员需要小心谨慎,以确保类型混淆不会导致无错误但意外的结果。
 
类型摘要
PHP共有八种类型:整数,双精度,布尔值,字符串,数组,对象,NULL和
资源。
?Integers是整数,不带小数点,如495。
? Doubles使用浮点数,如3.14159或49.0。
?Booleans只有两个可能的值:TRUE和FALSE。
? NULL是一种只有一个值的特殊类型:NULL。
?String是字符序列,如“PHP 4.0支持字符串操作”。
?Arrays是其他值的命名和索引集合。
?Objectsare是程序员定义的类的实例,可以打包其他类特定于类的值和函数的类型。
?Resources是保存对PHP外部资源(例如数据库连接)的引用的特殊变量。

其中,前五个是简单类型,下两个(数组和对象)是复合类型 - 复合类型可以打包任意类型的其他任意值,而简单类型不能。


简单类型
PHP中的简单类型(整数,双精度,布尔值,空值和字符串)应该对那些拥有编程经验的人来说应该是很熟悉的(尽管我们不会假设这些经验,并会详细解释)。唯一可能使C程序员感到惊讶的是PHP中有多少类型。
许多编程语言具有几种不同尺寸的数值类型,较大的编程语言允许更大范围的值,但是在存储器中占用更多的空间。例如,C语言具有短类型(对于相对小的整数),长类型(对于可能更大的整数)和int类型(其可以是中间的,但在实践中有时与短类型长类型相同)。它也有浮点类型,它们的精度不同。这种类型的选择在一个时代是有意义的,当内存使用和功能之间的折衷通常是痛苦。 PHP设计师做了我们认为是一个很好的决定,简化这个只有两个数字类型,对应于最大的积分和浮点类型在C.
整数
整数是最简单的类型 - 它们对应于简单的整数,包括正数和
负。整数可以分配给变量,也可以用在表达式中,如下所示:
$ int_var = 12345;
$ another_int = -12345 + 12345; //将等于零
读取格式
整数实际上可以用三种格式读取,这些格式对应于十进制(基本10),八进制(基本8)和十六进制(基本16)。十进制格式是默认值,八进制整数指定前导0,十六进制具有前导0x。任何格式都可以在前面加一个 - 符号,使整数为负数。例如:
$ integer_10 = 1000;
$ integer_8 = -01000;
$ integer_16 = 0x1000;
print(“integer_10:$ integer_10 <BR>”);
print(“integer_8:$ integer_8 <BR>”);
print(“integer_16:$ integer_16 <BR>”);
产生浏览器输出:
integer_10:1000
integer_8:-512
integer_16:4096
注意,读取格式仅影响整数在被读取时的转换方式 - 存储在$ integer_8中的值不记得它最初是写在基数8中。当然,这些数字以二进制格式表示;我们在前面的输出中看到它们的基本转换,因为这是打印和将int变量合并到字符串中的默认值。
范围
整数有多大(或小)?因为PHP整数对应于C longtype,
这反过来取决于您的机器的字大小,这是很难回答明确。然而,对于大多数常见的平台,最大的整数是2 31 - 1(或2,147,483,647),最小(最负的)整数是 - (2 31 - 1)(或-2,147,483,647)。
据我们所知,没有PHP常量(如MAXINTIN C)将告诉你实现上最大的整数。如果你真的需要比前面更大或更小的整数,PHP有一些任意精度函数 - 参见“数学”章节(第27章)的BC部分。
双打
Doubles是浮点数,例如:
$ first_double = 123.456;
$ second_double = 0.456
$ even_double = 2.0;
注意,$ even_double是一个“round”数字的事实不会使它成为一个整数。
整数和双精度存储在不同的底层格式,结果:
$ five = $ even_double + 3;
是一个双精度,而不是一个整数,即使它打印为5.然而,在几乎所有情况下,你应该
随意在数学表达式中混合双精度和整数,并让PHP整理出来
打字。
默认情况下,使用所需的最小小数位数打印两次 - 例如,
代码:
$ many = 2.2888800;
$ many_2 = 2.2111200;
$ few = $ many + $ many_2;
print(“$ many + $ many_2 = $ few <BR>”);
产生浏览器输出:
2.28888 + 2.21112 = 4.5
如果您需要更精细的打印控制,请参阅第8章中的打印功能。
 
读取格式
双倍的典型读取格式是-XY,其中 - 任选地指定负数,并且X和Y都是0和9之间的数字序列。如果数字在-1.0和1.0之间,则Xpart可以被省略,Ypart也可以被省略。前导或尾随零无效。所有以下都是合法的双重:
$ small_positive = 0.12345;
$ small_negative = -.12345
$ even_double = 2.00000;
$ still_double = 2 .;
此外,可以以科学记数法指定双精度,通过将字母e和期望的积分幂10加到先前格式的末尾,例如,2.2e-3将对应于2.2×10-3
数字的浮点部分不必限制在1.0和10.0之间的范围内。以下都是合法的:
$ small_positive = 5.5e-3;
print(“small_positive is $ small_positive <BR>”);
$ large_positive = 2.8e + 16;
print(“large_positive is $ large_positive <BR>”);
$ small_negative = -2222e-10;
print(“small_negative is $ small_negative <BR>”);
$ large_negative = -0.00189e6;
print(“large_negative is $ large_negative <BR>”);
上述代码生成以下浏览器输出:
small_positive为0.0055
large_positive为2.8E + 16
small_negative是-2.222E-07
large_negative是-1890

注意,正如八进制和十六进制整数一样,一旦PHP已经完成读取数字,读取格式是不相关的 - 前面的变量保留无论是否最初以科学计数法指定的内存。在打印这些值时,PHP正在做出自己的决定,以科学计数法打印更极端的值,但这与原始读取格式无关。


布尔
布尔值是真或假值,用于控制结构,如if语句的测试部分。正如我们将在第6章中看到的,布尔真值可以使用逻辑运算符组合,以使更复杂的布尔表达式。
布尔常量
PHP提供了两个常量,特别是用作Booleans:TRUE和FALSE,可以这样使用:
如果属实)
print(“This will always print <BR>”);
其他
print(“This will never print <BR>”);
将其他类型解释为布尔类型
以下是确定布尔类型的任何值的“真值”的规则:
?如果值是一个数字,如果完全等于零则为假,否则为真。
?如果值为字符串,如果字符串为空(具有零个字符)或字符串“0”,则为false,否则为true。
?NULL类型的值总是为false。
?如果值是复合类型(数组或对象),如果它不包含其他值,则为false,否则为true。对于包含具有已分配值的成员变量的值的对象。
?Valid资源是真实的(虽然一些功能返回资源,当他们成功将返回FALSE不成功)。
例子
以下变量中的每一个在其名称中使用时具有嵌入其真值的
布尔上下文。
$ true_num = 3 + 0.14159;
$ true_str =“试验和真实”
$ true_array [49] =“数组元素”; //见下一节
$ false_array = array();
$ false_null = NULL;
$ false_num = 999 - 999;
$ false_str =“”; // a string zero characters long
不要使用double作为布尔
请注意,虽然规则1暗示double 0.0转换为false布尔值,但是由于可能的舍入错误,将浮点表达式用作布尔表达式是危险的。例如:
$ floatbool = sqrt(2.0)* sqrt(2.0) - 2.0;
if($ floatbool)
print(“Floating-point Booleans are dangerous!<BR>”);
else
print(“This works ... this time。<BR>”);
print(“实际值是$ floatbool <BR>”);
设置为从两个平方根的平方减去2的结果的变量$ floatboolis - 这个计算的结果应该等于零,这意味着$ floatboolis为false。相反,我们得到的浏览器输出是:
浮点布尔是危险的!
实际值为4.4408920985006E-16
$ floatboolis的值非常接近0.0,但它是非零的,因此,意想不到的真实。整数在布尔角色中更安全 - 只要它们的算术只发生在其他整数,并且保持在整数大小之内,它们不应该被舍入误差。



空值NULL
布尔的世界可能看起来很小,因为布尔类型只有两个可能的值。然而,NULL类型将这种情况视为逻辑极端:NULL类型只有一个可能的值,即值为NULL。要给一个变量NULL值,简单地分配它像这样:
$ my_var = NULL;
特殊常量NULL被惯例大写,但实际上它是不区分大小写的;你可以只是键入:
$ my_var = null;
那么什么是NULL特别的? NULL表示缺少值。 (您可以将其视为非值的无价值。)已分配值NULL的变量几乎与尚未设置的变量几乎不可区分。特别地,已分配NULL的变量具有以下属性:
?在布尔上下文中求值为FALSE。
?当使用IsSet()测试时,返回FALSE。 (没有其他类型具有此属性。)
?如果将变量传递给函数并再次返回,PHP将不会打印警告,
而传递一个从未设置过的变量有时会产生警告。
NULL值最适用于您希望变量不具有有意值的情况,并且您希望向代码的读者和PHP明确这是您想要的。后一点在将变量传递给函数时尤其相关。
例如,如果在将变量$ authorizationhas传递给test_authorization()函数之前,变量$ authorizationhas从未被分配,则以下伪代码可能会打印警告(取决于错误报告设置)。
if(test_authorization($ authorization)){
//代码授予某种特权
}}
另一方面,代码如下:
$ authorization = NULL;
//可能或可能不会设置$ authorization的代码
if(test_authorization($ authorization)){
//代码授予某种特权
}}

不会导致非绑定变量警告,假设您已编写test_ authorization()来处理可能为NULL的参数。它还清楚地告诉读者该代码,你打算让变量缺少一个值,除非有一种情况下,它被分配。


字符串
字符串是字符序列,如下所示:
$ string_1 =“这是一个双引号的字符串。
$ string_2 ='这是一个稍长,单引号字符串';
$ string_39 =“这个字符串有三十九个字符。
$ string_0 =“”; //一个零字符的字符串
字符串可以用单引号或双引号括起来,在读取时具有不同的行为。单引号字符串几乎按字面处理,而双引号字符串用其值替换变量,以及特殊解释某些字符序列。
?
单引号字符串
除了几个特殊解释的字符序列,单引号字符串读入并存储其字符。下面的代码:
$ literally ='我的$变量不会打印!\\ n';
print($ literally);
产生浏览器输出:
我的$变量不会打印!\ n
单引号字符串也遵循不同类型的引号不会的一般规则
断开引用的字符串。这是合法的:
$ singly_quoted ='这个引号:“没有什么大不了”;
要在单引号字符串中嵌入单引号(例如撇号),请使用反斜杠对其进行转义,如下所示:
$ singly_quoted ='这个报价没有什么大不了的;
虽然在大多数上下文中,反斜杠在字面上解释为单引号字符串,但是您也可以使用两个反斜杠(\\)作为单个(非转义)反斜杠的转义序列。当你想要一个反斜杠作为字符串中的最后一个字符时,这是有用的,如:
$ win_path ='C:\\ InetPub \\ PHP \\';
print(“A Windows-style pathname:$ win_path <BR>”);
显示为
Windows样式的路径名:C:\ InetPub \ PHP \
我们可以使用单个反斜杠在输出中生成前两个反斜杠,但是在字符串结尾处的转义是必要的,因此不会转义结束引用。
这两个转义序列(\\和\')是对字面意义的唯一的认识单引号字符串。

双引号字符串
由双引号分隔的字符串(如“this”中所示)由PHP通过以下两种方式进行预处理:
?以反斜杠(\)开头的字符序列将替换为特殊字符。
?变量名称(以$开头)将替换为其值的字符串表示形式。逃逸序列替换是:
?用换行符替换\ n
?将\ ris替换为回车字符
?由制表符字符替换
?\ $由美元符号本身($)替换
?“由单个双引号(”)替换
?\\由单个反斜杠(\)替换
前三个替换使得很容易在字符串中可见地包含某些空白字符。 \ $序列允许您在需要时包括$符号,而不将其解释为变量的开始。 “\”序列存在,以便您可以包括双引号符号,而不终止双引号字符串。最后,因为\字符开始所有这些序列,你需要一种方法来包含那个字符,没有它开始一个转义序列 - 要做到这一点,你自己前面它。
与单引号字符串一样,相反类型的引号可以*包含而不使用转义字符:
$ has_apostrophe =“这里没有问题”;
单引号或双引号
PHP在构造字符串值之前,对双引号字符串(具有引号的字符串,如“this”)进行一些预处理。首先,变量被它们的值替换(如前面的例子)。要看到这个替换实际上是关于引用的字符串而不是printconstruct,请考虑以下代码:
$ animal =“antelope”; // first assignment
$ saved_string =“动物是$ animal <BR>”;
$ animal =“zebra”; //重新分配
print(“The animal is $ animal <BR>”); //第一个显示行
print($ saved_string); //第二显示行
你会期望什么输出?事实证明,您的浏览器将显示:
动物是斑马
动物是羚羊
浏览器按照这个顺序显示前面的输出。这是因为
“antelope”拼接到字符串$ saved_string中,然后重新分配$ animal变量。除了将变量值拼接成双引号字符串之外,PHP也取代了
一些特殊的多字符转义序列及其单字符值。的
最常用的是行尾序列(“\ n”) - 在读取一个字符串如:

“第一行\n \n \n第四行”


可变插值
每当双引号字符串中出现未转义的$符号时,PHP会尝试将以下内容解释为变量名,并将该变量的当前值拼接到字符串中。
发生什么样的替换取决于如何设置变量:
?如果变量当前设置为字符串值,则将该字符串插入(或拼接)到双引号字符串中。
?如果变量当前设置为非字符串值,则将该值转换为字符串,然后对该字符串值进行插值。
?如果当前未设置该变量,则PHP不会插入任何内容(或等效地,在空字符串中使用PHP拼接)。
一个例子:
$ this =“this”;
$ that =“that”;
$ the_other = 2.2000000000;
print(“$ this,$ not_set,$ that + $ the_other <BR>”);
产生PHP输出
this ,, that + 2.2 <BR>
这反过来,当在浏览器中看到,看起来像:
这,+ 2.2
如果你发现这个例子的任何部分令人费解,它值得工作通过什么PHP解析printstatement中的字符串。首先,请注意,字符串有四个$符号,每个都被解释为开始一个变量名。这些变量名称在变量名称中不合法的字符的第一次出现时终止。法律字符是字母,数字和下划线;前一个打印字符串中的直接终止字符是(按顺序)逗号,另一个逗号,加号(+)和左尖括号(<)。前两个变量绑定到字符串('this'和'that'),所以这些字符串在字面上拼接。下一个变量($ not_set)从未被分配,因此它从构造中的字符串中完全省略。最后,发现最后一个变量($ the_other)绑定到一个双精度值转换为一个字符串(“2.2”),然后将其拼接到我们构造的字符串。
有关将数字转换为字符串的更多信息,请参阅“分配和强制”下一节
正如我们在本章前面所说的,双引号字符串的所有这种解释发生在字符串被读取时,而不是当它被打印时。如果我们将示例字符串保存在变量中并稍后打印出来,它将反映前面代码中的变量值,即使变量在此期间已更改。
除了单引号和双引号之外,还有另一种方法来创建字符串(称为heredocsyntax),在某些方面,它更容易拼接变量的值。

字符串中的换行符
虽然PHP为换行符提供了一个转义序列(\n),但是很好知道,你可以在字符串的中间包含新行,PHP也将其视为换行符。这个功能在创建HTML字符串时很方便,因为浏览器会忽略换行符,所以我们可以使用换行符格式化字符串,使我们的PHP代码行很短:
print(“<HTML> <HEAD> </ HEAD> <BODY>我的HTML页面太大
以适合单行,但这并不意味着我需要多个打印语句!</ BODY> </ HTML>“);
我们在文本编辑器中通过在前两行结尾处输入Enter键来生成此语句 - 这些新行保留在字符串中,因此单个printstatement将生成三个不同的PHP输出行。 (您的里程数可能会根据您的文本编辑器而有所不同 - 如果您的编辑器自动换行显示它们,您可能会看到三行代码,实际上是一个长行。)当然,浏览器程序将忽略这些换行符,自己决定是否以及在哪里破坏显示中的行,但如果您在浏览器中使用“查看源代码”来查看HTML本身,您将看到行破坏。
限制
对于字符串长度没有人为的限制 - 在可用内存的边界,你应该能够制作任意长的字符串。