c – 具有位操作的快速strlen

前端之家收集整理的这篇文章主要介绍了c – 具有位操作的快速strlen前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我找到了这段代码
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,这确实是字符串的长度.

原文链接:https://www.f2er.com/c/117092.html

猜你在找的C&C++相关文章