php strlen(PHP中strlen()和mb_strlen()的区别浅析)

:暂无数据 2026-08-27 01:40:02 :0

php strlen(PHP中strlen()和mb_strlen()的区别浅析)

大家好,如果您还对php strlen不太了解,没有关系,今天就由本站为大家分享php strlen的知识,包括PHP中strlen()和mb_strlen()的区别浅析的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

本文目录

PHP中strlen()和mb_strlen()的区别浅析

在php中常见的计算字符串长度的函数有:strlen和mb_strlen.当字符全是英文字符的时候,两者是一样。这里主要比较一下,中英文混排的时候,两个计算结果。
先来看一个例子:
复制代码
代码如下:
《?php
//测试时文件的编码方式要是UTF8
$str=’中文a字1符’;
echo
strlen($str).’《br》’;//14
echo
mb_strlen($str,’utf8’).’《br》’;//6
echo
mb_strlen($str,’gbk’).’《br》’;//8
echo
mb_strlen($str,’gb2312’).’《br》’;//10
?》
结果分析:在strlen计算时,对待一个UTF8的中文字符是3个长度,所以“中文a字1符”长度是3*4+2=14,在mb_strlen计算时,选定内码为UTF8,则会将一个中文字符当作长度1来计算,所以“中文a字1符”长度是6。
利用这两个函数则可以联合计算出一个中英文混排的串的占位是多少(一个中文字符的占位是2,英文字符是1)
复制代码
代码如下:
echo
(strlen($str)
+
mb_strlen($str,’UTF8’))
/
2;
例如:“中文a字1符”
的strlen($str)值是14,mb_strlen($str)值是6,则可以计算出“中文a字1符”的占位是10:
PHP内置的字符串长度函数strlen无法正确处理中文字符串,它得到的只是字符串所占的字节数。
对于GB2312的中文编码,strlen得到的值是汉字个数的2倍,而对于UTF-8编码的中文,就是3倍的差异了(在UTF-8编码下,一个汉字占3个字节)。
采用mb_strlen函数可以较好地解决这个问题。
mb_strlen的用法和
strlen类似,只不过它有第二个可选参数用于指定字符编码。
例如得到UTF-8的字符串$str长度,可以用mb_strlen($str,’UTF-8’)。如果省略第二个参数,则会使用PHP的内部编码。内部编码可以通过mb_internal_encoding()函数得到。
注意:
mb_strlen并不是PHP核心函数,使用前需要确保在php.ini中加载了php_mbstring.dll
即确保“extension=php_mbstring.dll”这一行存在并且没有被注释掉,否则会出现未定义函数的问题。

PHP的count(数组)和strlen(字符串)的内部实现

翻了下PHP内核的定义,大概心中也有了答案了

count()和strlen()都是O(1)的时间复杂度

试想一下如果strlen()需要O(N)的复杂度那未免也太慢了,字符串长度起来的话服务器不是要直接挂掉吗

这两个函数都是典型的空间换时间的做法

我们可以先看看zvalue的结构:

typedef union _zvalue_value {
   long lval;             /* long value */
   double dval;            /* double value */
   struct {
      char *val;
      int len;
   } str;
   HashTable *ht;          /* hash table value */
   zend_object_value obj;
   zend_ast *ast;
} zvalue_value;

这里用的是一个联合体,当变量类型是string类型的时候附加存储多了一个len的整型变量,显而易见需要取长度直接利用记录值就可以了,自然就是O(1)

对于count()常用的参数类型应该为数组,对于继承Countable的类暂不作讨论

数组实现方式为Hashtable,直接看看他的结构吧

typedef struct _hashtable { 
    uint nTableSize;        // hash Bucket的大小,最小为8,以2x增长。
    uint nTableMask;        // nTableSize-1 , 索引取值的优化
    uint nNumOfElements;    // hash Bucket中当前存在的元素个数,count()函数会直接返回此值 
    ulong nNextFreeElement; // 下一个数字索引的位置
    Bucket *pInternalPointer;   // 当前遍历的指针(foreach比for快的原因之一)
    Bucket *pListHead;          // 存储数组头元素指针
    Bucket *pListTail;          // 存储数组尾元素指针
    Bucket **arBuckets;         // 存储hash数组
    dtor_func_t pDestructor;    // 在删除元素时执行的回调函数,用于资源的释放
    zend_bool persistent;       //指出了Bucket内存分配的方式。如果persisient为TRUE,则使用操作系统本身的内存分配函数为Bucket分配内存,否则使用PHP的内存分配函数。
    unsigned char nApplyCount; // 标记当前hash Bucket被递归访问的次数(防止多次递归)
    zend_bool bApplyProtection;// 标记当前hash桶允许不允许多次访问,不允许时,最多只能递归3次
#if ZEND_DEBUG
    int inconsistent;
#endif
} HashTable;

count直接获取nNumOfElements大小,所以也是O(1)

补充------------------------------------------------

count() 函数的定义在这里

/* {{{ proto int count(mixed var [, int mode])
   Count the number of elements in a variable (usually an array) */
PHP_FUNCTION(count)
{
    zval *array;
    zend_long mode = COUNT_NORMAL;
    zend_long cnt;
    zval *element;

    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_ZVAL(array)
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(mode)
    ZEND_PARSE_PARAMETERS_END();

    switch (Z_TYPE_P(array)) {
        case IS_NULL:
            php_error_docref(NULL, E_WARNING, “Parameter must be an array or an object that implements Countable“);
            RETURN_LONG(0);
            break;
        case IS_ARRAY:
            if (mode != COUNT_RECURSIVE) {
                //类型为数组时调用zend内核函数 zend_array_count()
                cnt = zend_array_count(Z_ARRVAL_P(array));
            } else {
                cnt = php_count_recursive(Z_ARRVAL_P(array));
            }
            RETURN_LONG(cnt);
            break;
        case IS_OBJECT: {
            zval retval;
            /* first, we check if the handler is defined */
            if (Z_OBJ_HT_P(array)-》count_elements) {
                RETVAL_LONG(1);
                if (SUCCESS == Z_OBJ_HT(*array)-》count_elements(array, &Z_LVAL_P(return_value))) {
                    return;
                }
            }
            /* if not and the object implements Countable we call its count() method */
            if (instanceof_function(Z_OBJCE_P(array), zend_ce_countable)) {
                zend_call_method_with_0_params(array, NULL, NULL, “count“, &retval);
                if (Z_TYPE(retval) != IS_UNDEF) {
                    RETVAL_LONG(zval_get_long(&retval));
                    zval_ptr_dtor(&retval);
                }
                return;
            }

            /* If There’s no handler and it doesn’t implement Countable then add a warning */
            php_error_docref(NULL, E_WARNING, “Parameter must be an array or an object that implements Countable“);
            RETURN_LONG(1);
            break;
        }
        default:
            php_error_docref(NULL, E_WARNING, “Parameter must be an array or an object that implements Countable“);
            RETURN_LONG(1);
            break;
    }
}

如果没有特别指定mode参数为 COUNT_RECURSIVE 的话(即作遍历),跳转到 zend 的数组计数函数 zend_array_count()

#define zend_hash_num_elements(ht) \
    (ht)-》nNumOfElements

...
...

static uint32_t zend_array_recalc_elements(HashTable *ht)
{
    zval *val;
    uint32_t num = ht-》nNumOfElements;
    
           ZEND_HASH_FOREACH_VAL(ht, val) {
               if (Z_TYPE_P(val) == IS_INDIRECT) {
                   if (UNEXPECTED(Z_TYPE_P(Z_INDIRECT_P(val)) == IS_UNDEF)) {
                       num--;
                   }
               }
    } ZEND_HASH_FOREACH_END();
    return num;
}

ZEND_API uint32_t zend_array_count(HashTable *ht)
{
    uint32_t num;
    if (UNEXPECTED(ht-》u.v.flags & HASH_FLAG_HAS_EMPTY_IND)) {
        num = zend_array_recalc_elements(ht);
        if (UNEXPECTED(ht-》nNumOfElements == num)) {
            ht-》u.v.flags &= ~HASH_FLAG_HAS_EMPTY_IND;
        }
    } else if (UNEXPECTED(ht == &EG(symbol_table))) {
        num = zend_array_recalc_elements(ht);
    } else {
        num = zend_hash_num_elements(ht);
    }
    return num;
}

IS_REFERENCE:间接 zval 指的就是其真正的值是存储在其他地方的。注意这个 IS_REFERENCE 类型是不同的,间接 zval 是直接指向另外一个 zval 而不是像 zend_reference 结构体一样嵌入 zval。

只有当数组中有 HASH_FLAG_HAS_EMPTY_IND 这个 flag 时(间接zval)才会对数组进行遍历校验,其他情况下都是直接取 数组(hash table) 里面的 nNumOfElements 的值,答案显而易见了,就是O(1)

php strlen的问题

php strlen() 函数返回字符串的长度。

《?php
$str = ’abcdef’;
echo strlen($str); // 6
$str = ’ ab cd ’;
echo strlen($str); // 7
?》

strlen(string)
参数 描述
string 必需。规定要检查的字符串。

//测试时文件的编码方式
《?php
$str=’中文a字1符’;
echo strlen($str).’《br》’;//14
echo mb_strlen($str,’utf8’).’《br》’;//6
echo mb_strlen($str,’gbk’).’《br》’;//8
echo mb_strlen($str,’gb2312’).’《br》’;//10
?》

文章分享结束,php strlen和PHP中strlen()和mb_strlen()的区别浅析的答案你都知道了吗?欢迎再次光临本站哦!

php strlen(PHP中strlen()和mb_strlen()的区别浅析)

本文编辑:admin

更多文章:


issued retroactively(FORM E上盖“ISSUED RETROACTIVELY”的问题,小女在线等待)

issued retroactively(FORM E上盖“ISSUED RETROACTIVELY”的问题,小女在线等待)

各位老铁们,大家好,今天由我来为大家分享issued retroactively,以及FORM E上盖“ISSUED RETROACTIVELY”的问题,小女在线等待的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站

2026年10月15日 10:30

f发音是什么?printf的返回值是什么

f发音是什么?printf的返回值是什么

大家好,关于f很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于f发音是什么的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

2026年10月15日 10:10

begin和start的区别(start与begin的区别)

begin和start的区别(start与begin的区别)

其实begin和start的区别的问题并不复杂,但是又很多的朋友都不太了解start与begin的区别,因此呢,今天小编就来为大家分享begin和start的区别的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

2026年10月15日 09:20

vant官网中文(范特365 是韩国化妆品VANT36.5吗)

vant官网中文(范特365 是韩国化妆品VANT36.5吗)

大家好,今天小编来为大家解答以下的问题,关于vant官网中文,范特365 是韩国化妆品VANT36.5吗这个很多人还不知道,现在让我们一起来看看吧!

2026年10月15日 09:10

特殊字符是指什么?正则表达式中一些特殊字符的用法

特殊字符是指什么?正则表达式中一些特殊字符的用法

大家好,特殊字符相信很多的网友都不是很明白,包括特殊字符是指什么也是一样,不过没有关系,接下来就来为大家分享关于特殊字符和特殊字符是指什么的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!

2026年10月15日 08:10

特殊符号网名大全花样符号(特殊符号昵称有哪些)

特殊符号网名大全花样符号(特殊符号昵称有哪些)

本篇文章给大家谈谈特殊符号网名大全花样符号,以及特殊符号昵称有哪些对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

2026年10月15日 07:30

prison break(越狱(prison break)到底是在讲个什么)

prison break(越狱(prison break)到底是在讲个什么)

各位老铁们好,相信很多人对prison break都不是特别的了解,因此呢,今天就来为大家分享下关于prison break以及越狱(prison break)到底是在讲个什么的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看

2026年10月15日 06:50

c程序设计第五版教学视频(求C程序设计(第五版)谭浩强教材源代码、视频课件等电子版资料!谢谢大家!)

c程序设计第五版教学视频(求C程序设计(第五版)谭浩强教材源代码、视频课件等电子版资料!谢谢大家!)

各位老铁们,大家好,今天由我来为大家分享c程序设计第五版教学视频,以及求C程序设计(第五版)谭浩强教材源代码、视频课件等电子版资料!谢谢大家!的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动

2026年10月15日 06:40

电脑教程入门(电脑初学入门)

电脑教程入门(电脑初学入门)

本篇文章给大家谈谈电脑教程入门,以及电脑初学入门对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

2026年10月15日 06:20

十六进制转二进制表(16进制转为2进制、8进制、10进制的公式)

十六进制转二进制表(16进制转为2进制、8进制、10进制的公式)

“十六进制转二进制表”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看十六进制转二进制表(16进制转为2进制、8进制、10进制的公式)!

2026年10月15日 06:10

最近更新

issued retroactively(FORM E上盖“ISSUED RETROACTIVELY”的问题,小女在线等待)
2026-10-15 10:30:03 浏览:0
如何制作短视频(短视频怎么制作)
2026-10-15 10:20:11 浏览:0
f发音是什么?printf的返回值是什么
2026-10-15 10:10:03 浏览:0
热门文章

标签列表