PHP_FUNCTION(array_diff)
{
zval *args;
int argc, i;
uint32_t num;
HashTable exclude;
zval *value;
zend_string *str, *key;
zend_long idx;
zval dummy; // 至少两个参数
if (ZEND_NUM_ARGS() < ) {
php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
return;
}
// 类型描述符:* variable arguments list (0 or more)
// 类型描述符:+ variable arguments list (1 or more)
// 参数存放在数组args中,argc保存参数个数
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
return;
} // 第一个参数不是数组,则报错
if (Z_TYPE(args[]) != IS_ARRAY) {
php_error_docref(NULL, E_WARNING, "Argument #1 is not an array");
RETURN_NULL(); // 返回NULL
} /* count number of elements */
// 检查所有参数是否是数组
num = ;
for (i = ; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + );
RETURN_NULL(); // 返回NULL
}
num += zend_hash_num_elements(Z_ARRVAL(args[i])); // 所有参数数组的元素个数累加
} // 元素个数num为0,返回第一个参数数组(空数组)
if (num == ) {
ZVAL_COPY(return_value, &args[]);
return;
} ZVAL_NULL(&dummy);
/* create exclude map */
zend_hash_init(&exclude, num, NULL, NULL, );
// 从第二个数组开始,所以数组元素保存到exclude
for (i = ; i < argc; i++) {
// 遍历数组
ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {
str = zval_get_string(value); // 数组元素值转为字符串
zend_hash_add(&exclude, str, &dummy); //
zend_string_release(str);
} ZEND_HASH_FOREACH_END();
} /* copy all elements of first array that are not in exclude set */
// 初始化返回值数组,大小和第一个数组一致。
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[])));
// 循环遍历第一个数组
ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(args[]), idx, key, value) {
str = zval_get_string(value); // 元素值转为字符串
if (!zend_hash_exists(&exclude, str)) { // exclude中找不到该值
// 插入到返回值数组中(差集),键名保留不变。
if (key) {
value = zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
} else {
value = zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, value);
}
zval_add_ref(value);
}
zend_string_release(str);
} ZEND_HASH_FOREACH_END(); zend_hash_destroy(&exclude);
}

php内置函数分析array_diff()的更多相关文章

  1. map内置函数分析所得到的思路

    map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...

  2. php内置函数分析之array_diff_assoc()

    static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */ { uint ...

  3. php内置函数分析之array_combine()

    PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...

  4. php内置函数分析之ucwords()

    PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...

  5. php内置函数分析之strtoupper()、strtolower()

    strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...

  6. php内置函数分析之ucfirst()、lcfirst()

    ucfirst($str) 将 str 的首字符(如果首字符是字母)转换为大写字母,并返回这个字符串. 源码位于 ext/standard/string.c /* {{{ php_ucfirst Up ...

  7. php内置函数分析之trim()

    官方手册中: 类似函数还有两个:ltrim() 和 rtrim().分别处理字符串的左侧.右侧. trim()的具体实现位于:ext/standard/string.c /* {{{ proto st ...

  8. php内置函数分析之str_pad()

    PHP_FUNCTION(str_pad) { /* Input arguments */ zend_string *input; /* Input string 输入字符串*/ zend_long ...

  9. php内置函数分析之array_fill_keys()

    PHP_FUNCTION(array_fill_keys) { zval *keys, *val, *entry; if (zend_parse_parameters(ZEND_NUM_ARGS(), ...

随机推荐

  1. awk命令1

    [root@a ~]# awk 'END{print NR}' c.txt       #没错,这就是文件的行数,当然,这种统计方法不是linux下最快的,但也是一种思路3[root@a ~]# wc ...

  2. RF通过命令执行用例及自定义报告与日志的位置

    1.执行整个项目下的所有用例: pybot 项目路径.例如: pybot D:\robotPS:robot项目里面所有用例 2.执行某个suit中的所有用例: pybot 项目路径\suit文件名称. ...

  3. java dwg转svg

    package com.example.demo.dxf2svg; import com.aspose.cad.InterpolationMode; import com.aspose.cad.Smo ...

  4. Windows10 家庭版安装 Docker Desktop

    开启 Hyper-V 开启后会有提示让重启电脑,重启就 OK :: 创建cmd (echo pushd "%~dp0" echo dir /b %SystemRoot%\servi ...

  5. Go开发[八]goroutine和channel

    进程和线程 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位. 一个进程可以创 ...

  6. windows 10 取消alt+tab的预览功能

    1.win+r  输入regedit打开注册表编辑器 2.HKEY_CURRENT_USER/SOFTWARE/Microsoft/Windows/CurrentVersion/Explorer 3. ...

  7. list,string,tuple,dictionary之间的转换

    list,string,tuple,dictionary之间的转换 类型 String List tuple dictionary String - list(str), str.split() tu ...

  8. MySQL 常用报错注入原理分析

    简介 这段时间学习SQL盲注中的报错注入,发现语句就是那么两句,但是一直不知道报错原因,所以看着别人的帖子学习一番,小本本记下来 (1) count() , rand() , group by 1.报 ...

  9. 应用安全 - 无文件式攻击 - 工具型攻击 - PowerShell - 汇总

    PowerShell 使用 | 命令 win+r ->powershell #启动Powershell窗口 get-host #查看版本 Get-Host | Select-Object Ver ...

  10. vue项目中,无需打包而动态更改背景图以及标题

    1.背景 今天,项目经理对已完成的项目提出了一个需求,即项目的基础功能目前针对于各个基层法院都适用,而对于不同的法院,我们每次都需要前端研发来更改所属法院的法院名称以及背景图,这样对于演示者来说是非常 ...