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. vue入门demo:用户管理3

    该入门demo是使用组件的方式实现,不涉及向后端发送请求 说明 把用户列表和添加用户拆分为两个组件,用户列表数据在父组件 获取用户列表:用户列表组件获取父组件的用户列表(父组件向子组件传值)1-1 1 ...

  2. lnmp 安装 访问 配置 laravel

    环境要求 Lnmp 一键安装包安装 php7.2+ Mysql 5.7 Innodb 开启 第一步 上传项目到 /home/wwwroot/default/ 或者composer命令行安装larave ...

  3. jdk的keytool生成jks和获取jks的信息,公匙

    1.生成jks.执行命令:keytool -genkeypair -alias mytest -keyalg RSA -keypass mypass -keystore mytest.jks -sto ...

  4. C 语言中的预处理

    C 语言中以 # 开头的就是预处理指令,例如 #include . 预处理指令的用途 所有的预处理指令都会在 GCC 编译过程的预处理步骤解析执行,替换为对应的内容.在下一步编译过程中,看不到任何预处 ...

  5. html5获取位置信息,h5获取位置信息

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. 社工 - By浏览器 - Google搜索技巧 - 汇总

    google基本语法 Index of: 使用它可以直接进入网站首页下的所有文件和文件夹中 intext: 将返回所有在网页正文部分包含关键词的网页 intitle: 将返回所有网页标题中包含关键词的 ...

  7. 【Qt开发】QThread中的互斥、读写锁、信号量、条件变量

    在gemfield的<从pthread到QThread>一文中我们了解了线程的基本使用,但是有一大部分的内容当时说要放到这片文章里讨论,那就是线程的同步问题.关于这个问题,gemfield ...

  8. 基于weui loading插件封装

    <!-- Loading.vue --> <template> <div id="loadingToast" v-if="show" ...

  9. swagger 访问格式

    boot工程格式如下 http://10.166.10.169:8085/swagger-ui.html 非boot工程加个自己项目名 http://10.166.10.169:8085/xxx/sw ...

  10. python 并发编程 多进程 互斥锁 目录

    python 并发编程 多进程 互斥锁 模拟抢票 互斥锁与join区别