回到笔记索引

1
2
3
4
5
6
7
<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
echo "Example function.\n";
return $retval;
}
?>
  • PHP 中的所有函数和类都具有全局作用域

  • PHP 不支持函数重载,也不可能取消定义或者重定义已声明的函数

  • 传参可以传值 $value,也可以引用 &$value 后者可以直接访问变量

  • 默认传参形式:$type = XXX,默认值必须是常量表达式,任何默认参数必须放在任何非默认参数的右侧

传参

1
2
3
4
<?php
function test(boolean $param) {}
test(true);
?>
  • 上述格式可以限制传参类型

  • 通过declare 严格类型,不再对函数传参进行自动转换,见严格类型


1
2
3
4
5
6
7
8
9
10
11
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}

echo sum(1, 2, 3, 4);
?>
  • (PHP 5.6)通过 ... 传递可变数量的参数列表
1
2
3
4
5
6
7
8
9
10
11
<?php
function sum() {
$acc = 0;
foreach (func_get_args() as $n) {
$acc += $n;
}
return $acc;
}

echo sum(1, 2, 3, 4);
?>
  • (PHP 5.5 -)使用函数 func_num_args(),func_get_arg(),和 func_get_args()

返回值

  • 函数不能返回多个值,但可以通过返回一个数组来得到类似的效果

  • 从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用运算符 &

1
2
3
4
5
6
7
8
<?php
function &returns_reference()
{
return $someref;
}

$newref =& returns_reference();
?>
  • (PHP 7)可以指定返回值,受到 严格类型 影响
1
2
3
4
5
<?php
function sum($a, $b): float {
return $a + $b;
}
?>

可变函数

1
2
3
4
5
6
7
8
9
$func = 'foo';
$func(); // 调用 foo()

$func = 'bar';
$func(); // 调用 bar()

$func = array("Foo", "bar");
$func(); // 调用了 Foo 类的 bar() 静态方法
// 或者表示 调用了 Foo 实例的 bar() 成员对象
  • 也可以用可变函数的语法来调用一个对象的方法

匿名(闭包)函数(PHP 5.3)

1
2
3
4
5
6
7
8
9
<?php
// 将匿名函数赋值给变量
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};

$greet('World');
?>
1
2
3
4
$example = function () use ($message) {
var_dump($message); // 闭包继承父作用域
};
echo $example();
  • (PHP 5.4)对匿名函数使用 static 可以防止类对其绑定(变量 $this)

生成器

yield 关键字:

  • yield $id; $data = (yield $value);

  • yield $id => $fields; $data = (yield $key => $value); 指定键名

  • yield; 返回 NULL

  • 生成器返回的迭代对象可以迭代引用变量:

    1
    2
    3
    4
    5
    function &gen_reference() {
    $value = null;
    yield $value;

    }
  • yield from 调用另外的可迭代对象

回到笔记索引

  • 常量前面没有美元符号 echo CONSTANT;

  • 只能包含标量数据

  • 使用形如 define("FOO","something"); 定义常量,PHP 5.3.0 以后,可以使用 const 关键字

  • 全部作用域可用

魔术常量

有值随着它们在代码中的位置改变而改变:

  • __LINE__ 文件中的当前行号。
  • __FILE__ 文件的完整路径和文件名;自 PHP 4.0.2 总是包含一个绝对路径
  • __DIR__ 文件所在的目录(PHP 5.3.0 中新增)
  • __FUNCTION__ 函数名称,返回该函数被定义时的名字(区分大小写)
  • __CLASS__ 类的名称,返回该类被定义时的名字(区分大小写);类名包括其被声明的作用区域(例如 Foo\Bar);自 PHP 5.4 起对 Trait 也起作用,调用 trait 方法的类的名字。
  • __TRAIT__ Trait 的名字(PHP 5.4.0 新加);返回 trait 被定义时的名字(区分大小写)。Trait 名包括其被声明的作用区域(例如 Foo\Bar)
  • __METHOD__ 类的方法名(PHP 5.0.0 新加);返回该方法被定义时的名字(区分大小写)
  • __NAMESPACE__ 当前命名空间的名称(区分大小写);此常量是在编译时定义的(PHP 5.3.0)

回到笔记索引

类(包括抽象类和 traits)、接口、函数和常量 收到到命名空间影响,


  • namespace 必须在其它所有代码之前(包括 HTML、除了 declare)声明命名空间:
1
2
3
4
5
6
7
8
9
<?php
namespace MyProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }

?>


namespace MyProject\Sub\Level 定义了子命名空间。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}

namespace { // 全局命名空间
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

多个命名空间使用大括号区分


使用时类似文件系统:

1
2
3
4
5
6
7
8
/* 非限定名称 */
foo(); // 解析为 Foo\Bar\ foo,相对路径

/* 限定名称 */
subnamespace\foo(); // 解析为函数 Foo\Bar\ subnamespace\foo,相对路径

/* 完全限定名称 */
\Foo\Bar\foo(); // 解析为函数 Foo\Bar\foo,绝对路径
  • 访问任意全局类、函数或常量,都可以使用完全限定名称

  • 动态访问时必须使用使用完全限定名称,前导反斜杠不必要

  • 如果当前命名空间中不存在该函数或常量,PHP 会退而使用全局空间中的函数或常量

具体使用

1
2
3
4
5
6
use My\Full\Classname as Another, My\Full\NSname; // 多个引用

// (PHP 5.6)
use function My\Full\functionName;
use function My\Full\functionName as func;
use const My\Full\CONSTANT;

可以引入命名空间并给予别名,必须为完全限定,前导不推荐

回到笔记索引

算术运算符

-$a 取反

$a + $b 加法

$a - $b 减法

$a * $b 乘法

$a / $b 除法

$a % $b 取模

$a ** $b 求幂(PHP 5.6)

  • 除法运算符总是返回浮点数

  • 取模运算符的操作数在运算之前都会转换成整数,和被除数的符号(正负号)相同

  • 亦有 数学函数 供使用

数组运算符

  • $a + $b 联合:将后者接在前者后面,并忽略后者与前者相同部分

  • $a == $b 相等:如果二者数组元素相同

  • $a === $b 全等:如果二者完全相同,包括顺序

  • $a != $b 不等

  • $a <> $b 不等

  • $a !== $b 不全等

位运算符

  • $a & $b And(按位与)b

  • $a | $b Or(按位或)

  • $a ^ $b Xor(按位异或)

  • ~ $a Not(按位取反)

  • $a << $b Shift left(左移 乘二)

  • $a >> $b Shift right(右移 除二)

比较运算符

  • $a == $b 等于

  • $a === $b 全等

  • $a != $b 不等

  • $a <> $b 不等

  • $a !== $b 不全等

  • $a < $b 小与

  • $a > $b 大于

  • $a <= $b 小于等于

  • $a >= $b 大于等于

  • $a <=> $b 结合比较运算符 当$a 小于、等于、大于 than $b 时 分别返回一个小于、等于、大于 0 的 integer 值(PHP7)

不使用全(不)等时会存在自动转换:

  • nullstringstring 比较:将 NULL 转换为 "",进行数字或词汇比较

  • boolnull 与 任何其它类型 比较:转换为 boolFALSE < TRUE

  • object 与 object 比较:内置类可以定义自己的比较,不同类不能比较,相同类和数组同样方式比较属性(PHP 4 中),PHP 5 有其自己的说明

  • string,resource 或 number 与 string,resource 或 number 比较:将字符串和资源转换成数字,按普通数学比较

  • array 与 array 比较:具有较少成员的数组较小,如果运算数 1 中的键不存在于运算数 2 中则数组无法比较,否则挨个值比较(见下例)

  • object 与 任何其它类型 比较:object 总是更大

  • array 与 任何其它类型 比较:array 总是更大

三元运算符

表达式 (expr1) ? (expr2) : (expr3)expr1 求值为 TRUE 时的值为 expr2,在 expr1 求值为 FALSE 时的值为 expr3

表达式 expr1 ?: expr3 在 expr1 求值为 TRUE 时返回 expr1,否则返回 expr3(PHP 5.3)

合并运算符

当 expr1 为 NULL,表达式 (expr1) ?? (expr2) 等同于 expr2,否则为 expr1。

错误控制运算符

PHP 支持一个错误控制运算符:@;当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。

对新手来说一个简单的规则就是:如果能从某处得到值,就能在它前面加上 @ 运算符

执行运算符

PHP 支持一个执行运算符:反引号,PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回

自增减运算符

  • ++$a 先增
  • $a++ 后增
  • --$a 前减
  • $a-- 后减

在处理字符变量的算数运算时例如,在 PHP 中 $a = 'Z'; $a++; 将把 $a 变成 'AA';字符变量只能递增,不能递减,并且只支持纯字母(a-z 和 A-Z)

逻辑运算符

  • $a and $b And(逻辑与)

  • $a or $b Or(逻辑或)

  • $a xor $b Xor(逻辑异或)

  • ! $a Not(逻辑非)

  • $a && $b And(逻辑与)

  • $a || $b Or(逻辑或)

与、或有两种表达,优先级不同,and or 垫底


存在如下操作:

$a = b() or c()

如果 b() 返回 false 则 c() 才会执行

运算符

  • 运算符优先级

  • 算术运算符

  • 赋值运算符

=+=-=*=

  • 位运算符

  • 比较运算符

  • 错误控制运算符

  • 执行运算符

  • 递增/递减运算符

  • 逻辑运算符

  • 字符串运算符

  • 数组运算符

  • 类型运算符

instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例

字符串运算符

  • . 连接运算符
  • .= 连接赋值运算符,与 += -= 类似

运算符优先级

https://www.php.net/manual/zh/language.operators.precedence.php

回到笔记索引

Declare

1
2
3
4

declare (directive)
statement

  • ticks

    Tick(时钟周期)是一个在 declare 代码段中解释器每执行 N 条可计时的低级语句就会发生的事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    <?php
    // these are the same:

    // you can use this:
    declare(ticks=1) {
    // entire script here
    }

    // or you can use this:
    declare(ticks=1);
    // entire script here
    ?>

  • encoding

    可以用 encoding 指令来对每段脚本指定其编码方式

    1
    2
    3
    4
    5
    6

    <?php
    declare(encoding='ISO-8859-1');
    // code here
    ?>

For 一家

1
2
3
4

for (expr1; expr2; expr3)
statement

亦可:

1
2
3
4
5
6

for (expr1; expr2; expr3):
statement;
...
endfor;

foreach 数组对象遍历专业户:

1
2
3
4
5
6
7

foreach (array_expression as $value) // 获取值
statement

foreach (array_expression as $key => $value) //获取值与键
statement

当 foreach 开始执行时,数组内部的指针会自动指向第一个单元

If 一家

可以(花括号在内部单句时不必要):

1
2
3
4
5
6
7
8
9
10
11

<?php
if ($a > $b) {
echo "a is bigger than b";
} elseif ($a == $b) {
echo "a is equal to b";
} else {
echo "a is smaller than b";
}
?>

还可以:

1
2
3
4
5
6
7
8
9
10
11

<?php
if ($a > $b):
echo "a is bigger than b";
else if ($a == $b):
echo "a is equal to b";
else:
echo "a is smaller than b";
endif;
?>

Switch

执行 == 比较而不是 ===

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<?php
switch ($i) {
case 0: // 会落到下一个判断
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default: // 没有匹配的话:
echo "i is not equal to 0, 1 or 2";
}
?>

另一种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<?php
switch ($i):
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default:
echo "i is not equal to 0, 1 or 2";
endswitch;
?>

While 一家

while:

1
2
3
4
5

while (expr) {
statement
}

还可以:

1
2
3
4
5
6

while (expr):
statement
...
endwhile;

do…while,do 内至少执行一遍:

1
2
3
4
5
6
7
8

<?php
$i = 0;
do {
echo $i;
} while ($i > 0);
?>

错误处理

1
2
3
4
5
6
7
try {
throw new Exception('Division by zero.'); // 需要捕获错误的部分
} catch (Exception $e) {
echo $e; // 出现相应错误时运行(这里打印了错误),然后便跳出
} finally {
// 无论如何都执行
}

回到笔记索引

  • 传值赋值:$a = 1;

  • 引用赋值:$b = &$a; 指向同一内存;只有有名字变量才可以

另:PHP 有大量预定义变量,见文档

引用

$a =& $b

引用使得两个变量名指向同一个内存地址

  • 引用传递:可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值:
1
2
3
4
5
6
function foo(&$var)
{
$var++;
}

foo($a); // 调用无需引用符号
  • 引用返回,见函数,不必要则无需使用

  • 销毁引用:与销毁变量类似

1
2
3
4
5
<?php
$a = 1;
$b =& $a;
unset($a);
?>
  • global 相当于引用全局变量

  • $this 永远是调用它的对象的引用

作用域

PHP 使用函数作用域

include 不会产生新作用域

global 关键字可以访问全局作用域

$GLOBALS['a'] 超全局变量亦可,其在全部作用域中可用

static 定义静态,只会进行一次初始化,声明不可以传值表达式

可变变量

对形如 $$a ${$a} 赋值可以改变 a 的变量名

超全局变量 不能用作可变变量;$this 也不能被动态引用。

回到笔记索引

标量类型

boolean(布尔型)

FALSE:

  • 布尔值 FALSE 本身 -整型值 0(零)
  • 浮点型值 0.0(零)
  • 空字符串,以及字符串 "0"
  • 不包括任何元素的数组 - 特殊类型 NULL(包括尚未赋值的变量)
  • 从空标记生成的 SimpleXML 对象

TRUE:

  • 其余是 TRUE(包括任何资源 和 NAN

integer(整型)

范围:32 位有符号

表示:

  • 小数 decimal : [1-9][0-9]\* | 0

  • 十六进制 hexadecimal : 0[xX][0-9a-fa-f]+

  • 八进制 octal : 0[0-7]+

  • 二进制 binary : 0b[01]+

  • 整型 integer : [+-]?decimal | [+-]?hexadecimal | [+-]?octal | [+-]?binary

转换:

  • 用 (int) 或 (integer) 强制转换

  • 当从浮点数转换成整数时,将向下取整

  • 如果给定的一个数超出了 integer 的范围,将会被解释为 float

  • resource 转为整型时为 分配的唯一资源号

  • 布尔 FALSE 将产生出 0 ,TRUE 将产生出 1

  • float(浮点型,也称作 double)

    表示:

    • LNUM [0-9]+

    • DNUM ([0-9]_[\.]{LNUM}) | ({LNUM}[\.][0-9]_)

    • EXPONENT_DNUM [+-]?(({LNUM} | {DNUM}) [eE][+-]? {LNUM})

      NaN:

    • NAN 代表着任何不同值,为不可描述,需要 is_NaN() 方法

string(字符串)

PHP 只能支持 256 的字符集,因此不支持 Unicode

表示:

  • 单引号 '

    只有 \\\' 会被转义

    在单引号字符串中的变量和特殊字符的转义序列将不会被替换

  • 双引号 "

    可以使用转义

    变量会被解析

  • Heredoc 结构

    Heredoc 可以进行解析操作,使用双引号标记(5.3.0 前不需要)

    Heredocs 结构不能用来初始化类的属性
    PHP 5.3.0 ,此限制仅对 heredoc 包含变量时有效,同时 Heredoc 结构可以初始化静态变量和类的属性和常量,
    示例:

    1
    2
    3
    4
    5
    <<<"标记"
    My name is "$name". I am printing some $foo->foo.
    Now, I am printing some {$foo->bar[1]}.
    This should print a capital 'A': \x41
    标记;

    输出:

    My name is “MyName”. I am printing some Foo.
    Now, I am printing some Bar2.
    This should print a capital ‘A’: A

  • Nowdoc 结构

    nowdoc 中不进行解析操作,使用单引号标记

    nowdoc 结构可以用在任意的静态数据环境中

    1
    2
    3
    4
    5
    <<<'EOT'
    My name is "$name". I am printing some $foo->foo.
    Now, I am printing some {$foo->bar[1]}.
    This should not print a capital 'A': \x41
    EOT;

    变量解析:

    • 简单规则: $ 会尽量匹配变量

    • 复杂规则: 使用形如 {$great}

其他:

  • 可以像数组一样读取写入

  • 字符串可以用 ‘.’(点)运算符连接起来

  • 一个值可以通过在其前面加上 (string) 或用 strval() 函数来转变成字符串

    • boolean 的 TRUE 被转换成 string 的 “1”,FALSE 被转换成 “” (空字符串)

    • 一个整数 integer 或浮点数 float 被转换为数字的字面样式的 string

    • 数组 array 总是转换成字符串 “Array”

    • 资源 resource 总会被转变成 “Resource id #1” 这种结构的字符串

    • NULL 总是被转变成空字符串

  • 转为数值时,如果该字符串没有包含 ‘.’,‘e’ 或 ‘E’ 并且其数字值在整型的范围之内,该字符串将被当成 integer 来取值。其它所有情况下都被作为 float 来取值

复合类型

array(数组)

  • 定义:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    $array = array(
    "key" => "value",
    "key" => "value",
    );

    // 自 PHP 5.4 起
    $array = [
    "key" => "value",
    "key" => "value",
    ];
    ?>

    key 可以是 integer 或者 string。value 可以是任意类型

    对于 key:

    • 字符串(整型形式)、布尔、浮点(忽略小数部分)会被尽量转换为整型

    • Null 会被转换为空字符串

    • 数组和对象不可作为 key

    • 为可选项,当未指定时,会自动命名

    • 访问与赋值

      • 访问可以使用 ['$i']{'$1'},注意引号

      • 赋值就那个样子,删除使用 unset() 方法,赋值时,注意自动命名

    • 转换

      • 如果将一个值转换为数组,将得到一个仅有一个元素的数组,其下标为 0

      • 如果一个 object 类型转换为 array,则结果为一个数组,会导致一些不可预知的行为

      • 将 NULL 转换为 array 会得到一个空的数组

object(对象)

  • 声明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    class foo {
    function do_foo() {
    echo "Doing foo.";
    }
    }

    $bar = new foo;
    $bar->do_foo();
    ?>

    详见面向对象

  • 转换

  • 如果其它任何类型的值被转换成对象,将会创建一个内置类 stdClass 的实例

  • 如果该值为 NULL,则新的实例为空

  • array 转换成 object 将使键名成为属性名并具有相对应的值

  • 对于其他值,会包含进成员变量名 scalar

callable(可调用)

  • 自 PHP 5.4 起可用 callable 类型指定回调类型 callback

  • PHP 是将函数以 string 形式传递的,一个已实例化的 object 的方法被作为 array 传递,下标 0 包含该 object,下标 1 包含方法名。 在同一个类里可以访问 protected 和 private 方法

1
2
3
4
5
6
7
8
9
// Type 1: Simple callback
call_user_func('my_callback_function');

// Type 2: Static class method call
call_user_func(array('MyClass', 'myCallbackMethod'));

// Type 3: Object method call
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));

伪类型

并不是实际存在的类型,而是类型的集合

mixed(混合类型)

一个参数可以接受多种不同的(但不一定是所有的)类型

number(数字类型)

一个参数可以是 integer 或者 float

callback(回调类型,又称为 callable)

PHP 5.4 引入 callable 类型之前使用 了 callback 伪类型

array|object(数组 | 对象类型)

字面意思

void (无类型)

无返回值或不接受参数

伪变量

$...当一个函数可以接受任意个参数时使用此变量名
`

特殊类型

resource(资源)

资源 resource 是一种特殊变量,保存了到外部资源的一个引用。

NULL(无类型)

特殊的 NULL 值表示一个变量没有值。NULL 类型唯一可能的值就是 NULL:

  • 被赋值为 NULL。

  • 尚未被赋值。

  • 被 unset()。

数据类型

  • double 和 float 是相同的

  • PHP 使用鸭子类型

  • 如果想查看某个表达式的值和类型,用 var_dump() 函数

  • 如果只是想得到一个易读懂的类型的表达方式用于调试,用 gettype() 函数。要检验某个类型,不要用 gettype(),而用 is_type 函数

  • 对其使用 强制转换 或者 settype() 函数,可以转换类型:

    • 强制转换有:

      • (int), (integer) - 转换为整形 integer

      • (bool), (boolean) - 转换为布尔类型 boolean

      • (float), (double), (real) - 转换为浮点型 float

      • (string) - 转换为字符串 string

      • (array) - 转换为数组 array

      • (object) - 转换为对象 object

      • (unset) - 转换为 NULL (PHP 5)

      • (binary) - 转换为 二进制 (PHP 5.2.1)

  • 变量根据其当时的类型在特定场合下会表现出不同的值。

C 代码结构

笔记索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h> // 加载头文件

/* 多行注释 */
// 单行注释

int main(int argc, char *argv[]) // 返回值为 int,接受两个命令行参数
{
int age = 10; // 变量声明
int height = 72;

printf("I am %d years old.\n", age); // C 风格输出格式化
printf("I am %d inches tall.\n", height);

return 0; // 返回值
}
阅读全文 »

笔记索引

CMake 简单使用

命令行

1
2
3
4
生成构建系统
cmake [<options>] <path-to-source>
cmake [<options>] <path-to-existing-build>
cmake [<options>] -S <path-to-source> -B <path-to-build>
  • -D <var>:<type>=<value> 设定变量
  • -G <generator-name> 指定生成器
  • --graphviz=[file] 生成依赖图
  • -A <platform-name> 指定平台
1
2
构建一个项目
cmake --build <dir> [<options>] [-- <build-tool-options>]
阅读全文 »

编译流程

笔记索引

编译一般可以分为三个阶段:

预处理 Preprocessing

执行预处理语句(#define 等)

编译和汇编 Compilation & assembly

经过两步将预处理器产生的代码编译成目标文件(object file):

  1. 代码编译成底层汇编代码。在这一步中,编译器会对代码进行检查优化,指出各种错误

  2. 汇编器将上一步生成的汇编代码逐行转换成字节码(也就是机器码)

链接 Linking

链接器利用编译器产生的目标文件,生成最终结果

在这一阶段,编译器将把上一阶段中编译器产生的各种目标文件链接起来形成一整个链接库或者可执行文件

0%