var_dump(strpos('mrwagon',626));

var_dump(strpos('mrwagon',626)); 为什么输出int(1)

阅读 2.1k
1 个回答

看看这个函数的核心C代码实现:

    if (Z_TYPE_P(needle) == IS_STRING) {
        if (!Z_STRLEN_P(needle)) {
            php_error_docref(NULL, E_WARNING, "Empty needle");
            RETURN_FALSE;
        }

        found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
                            Z_STRVAL_P(needle),
                            Z_STRLEN_P(needle),
                            ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
    } else {
        //当不是字符串时,需要将参数转换为char类型
        if (php_needle_char(needle, needle_char) != SUCCESS) {
            RETURN_FALSE;
        }
        needle_char[1] = 0;

        php_error_docref(NULL, E_DEPRECATED,
            "Non-string needles will be interpreted as strings in the future. " \
            "Use an explicit chr() call to preserve the current behavior");
        //查找转换为char类型后的字符串位置
        found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
                            needle_char,
                            1,
                            ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
    }

static int php_needle_char(zval *needle, char *target)
{
    switch (Z_TYPE_P(needle)) {
        case IS_LONG:
            //当提供的参数是long类型时,直接转换为数字对应的字符
            *target = (char)Z_LVAL_P(needle);
            return SUCCESS;
        case IS_NULL:
        case IS_FALSE:
            *target = '\0';
            return SUCCESS;
        case IS_TRUE:
            *target = '\1';
            return SUCCESS;
        case IS_DOUBLE:
            *target = (char)(int)Z_DVAL_P(needle);
            return SUCCESS;
        case IS_OBJECT:
            *target = (char) zval_get_long(needle);
            return SUCCESS;
        default:
            php_error_docref(NULL, E_WARNING, "needle is not a string or an integer");
            return FAILURE;
    }
}

如果你提供的needle 参数不是字符串,则会调用php_needle_char 方法转换为参数对应的字符串,题目中就是626对应的ASCII字母为r

你也可以用chr(626)看下输出的是不是r

C源码: https://github.com/php/php-sr...

ASCII中并没有 626 这个值,那么为什么chr方法会将 626 转换成了 r 呢? 看看C代码是如何实现的:

int zend_compile_func_chr(znode *result, zend_ast_list *args) /* {{{ */
{

    if (args->children == 1 &&
        args->child[0]->kind == ZEND_AST_ZVAL &&
        Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_LONG) {
        //主要原因是将值跟 0xff 做了与运算。0xff的十进制是255.
        zend_long c = Z_LVAL_P(zend_ast_get_zval(args->child[0])) & 0xff;

        result->op_type = IS_CONST;
        ZVAL_INTERNED_STR(&result->u.constant, ZSTR_CHAR(c));
        return SUCCESS;
    } else {
        return FAILURE;
    }
}

任何一个数字,与 0xff 做与运算,其结果不会大于255,是处于 ASCII 码表达的范围内的。 626&0xff=114, 114 对应的字母是 r

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题