c – 具有位 *** 作的快速strlen

c – 具有位 *** 作的快速strlen,第1张

概述我找到了这段代码 int strlen_my(const char *s){ int len = 0; for(;;) { unsigned x = *(unsigned*)s; if((x & 0xFF) == 0) return len; if((x & 0xFF00) == 0) return len + 1; 我找到了这段代码
int strlen_my(const char *s){    int len = 0;    for(;;)    {        unsigned x = *(unsigned*)s;        if((x & 0xFF) == 0) return len;        if((x & 0xFF00) == 0) return len + 1;        if((x & 0xFF0000) == 0) return len + 2;        if((x & 0xFF000000) == 0) return len + 3;        s += 4,len += 4;    }}

我很想知道它是如何工作的. ¿任何人都可以解释它是如何工作的?

解决方法 按位AND与1将从另一个 *** 作数中检索位模式.含义,10101& 11111 = 10101.如果该按位AND的结果为0,则我们知道另一个 *** 作数为0.当使用0xFF(1)对单个字节进行AND运算时,结果为0将指示NulL字节.

代码本身在四字节分区中检查char数组的每个字节.注意:此代码不可移植;在另一台机器或编译器上,unsigned int可能超过4个字节.使用uint32_t数据类型来确保32位无符号整数可能会更好.

首先要注意的是,在小端机器上,构成字符数组的字节将以相反的顺序读入无符号数据类型;也就是说,如果当前地址的四个字节是对应于abcd的位模式,则无符号变量将包含对应于dcba的位模式.

第二个是C中的十六进制数常量导致一个int大小的数字,在位模式的小端有指定的字节.这意味着,当使用4字节整数进行编译时,0xFF实际上是0x000000FF. 0xFF00是0x0000FF00.等等.

所以程序基本上是在四个可能的位置寻找NulL字符.如果当前分区中没有NulL字符,它将前进到下一个四字节插槽.

以char数组abcdef为例.在C中,字符串常量总是在末尾有空终止符,因此在该字符串的末尾有一个0x00字节.

它的工作原理如下:

将“abcd”读入unsigned int x:

x: 0x64636261 [ASCII representations for "dcba"]

检查每个字节是否有空终止符:

0x64636261& 0x000000FF  0x00000061 != 0,0x64636261& 0x0000FF00  0x00006200 != 0,

并检查其他两个位置;此4字节分区中没有空终止符,因此前进到下一个分区.

将“ef”读入unsigned int x:

x: 0xBF006665 [ASCII representations for "fe"]

注意0xBF字节;这超过了字符串的长度,所以我们从运行时堆栈中读取垃圾.它可能是任何东西.在不允许未对齐访问的计算机上,如果字符串后面的内存不是1字节对齐,则会崩溃.如果字符串中只剩下一个字符,我们将读取两个额外的字节,因此与char数组相邻的内存对齐必须是2字节对齐的.

检查每个字节是否有空终止符:

0xBF006665& 0x000000FF  0x00000065 != 0,0xBF006665& 0x0000FF00  0x00006600 != 0,0xBF006665& 0x00FF0000  0x00000000 == 0 !!!

所以我们返回len 2; len是4,因为我们将它一次增加4,所以我们返回6,这确实是字符串的长度.

总结

以上是内存溢出为你收集整理的c – 具有位 *** 作的快速strlen全部内容,希望文章能够帮你解决c – 具有位 *** 作的快速strlen所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1236804.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存