百度面试题:自己实现strlen,考虑32位,64位机器,考虑性能

没办法, 现在的大公司面试就面这个, 你不得不研究下底层的实现.

要点:
1) 字长边界对齐以便加快速度. 对齐时也要考虑机器的位数哦.

2) 一次测试4个(或者8个)字节中是否含零的技巧.
3) 需要自适应32bit/64bit机器. 
   定义magic变量是要使用long, 并且是unsigned的, 如果是unsigned int就不行, 只能在32位下用.
   判断字长时要sizeof(long) 而不是sizeof(int)

如何一次测试4个字节是否含零?
一个关键技巧是通过异或操作判断经过运算后一个数的那些bit位未发生变化.结果为1的bit位未发生变化.
类似的,&操作可以判断那些位发生了变化.
举例,两个数a,b, 试比较两个数有那些bit位是相同的?
a^~b , 结果中bit位为1的位是相同的.
a&~b , 结果中bit位为1的位是不同的.

一片博文讲解的很精彩
strlen高效实现 
http://blog.csdn.net/lonelysky/article/details/6614422

 

#include <stdio.h>
#include <string.h>
 
int my_strlen(const char * str)
{
    const char * pstr = str;
    
    // 先将地址边界对齐  & 操作更高效, 避免了%取余运算
    //for (; (unsigned long)pstr%(sizeof(long)) != 0; ++pstr)
    for (; (unsigned long)pstr & (sizeof(long)-1) != 0; ++pstr)
    {
        if (pstr[0] == '\0')
            return pstr - str;
    }
 
    unsigned long himagic = 0x80808080;
    unsigned long lomagic = 0x01010101;
 
    // 如果是64位
    if (sizeof(long) > 4)
    {
        himagic = ((himagic << 16) << 16) | himagic;
        lomagic = ((lomagic << 16) << 16) | lomagic;
    }
 
    unsigned long longword = 0;
    for (;; pstr+=sizeof(long))
    {
        longword = *(unsigned long*)pstr;
 
        // (longword - lomagic) & ~longword 可测试出, 相减之后longword变量的那些bit发生了改变
        // ... & himagic 可测试出, 变化的那些bit位中是否包含各个字节的最高位
        if (((longword - lomagic) & ~longword & himagic) != 0)
        {
            if (pstr[0] == '\0')
                return pstr - str;
            if (pstr[1] == '\0')
                return pstr - str + 1;
            if (pstr[2] == '\0')
                return pstr - str + 2;
            if (pstr[3] == '\0')
                return pstr - str + 3;
            if (sizeof(long) > 4)
            {
                if (pstr[4] == '\0')
                    return pstr - str + 4;
                if (pstr[5] == '\0')
                    return pstr - str + 5;
                if (pstr[6] == '\0')
                    return pstr - str + 6;
                if (pstr[7] == '\0')
                    return pstr - str + 7;
            }
        }
    }
 
    // never come to here...
    return 0;
}
int main()
{
    char * str = "helloworldaaaaa";
    int ret = 0;
 
    ret = my_strlen(str+1);
    printf("len : %d\n", ret);
 
    ret = strlen(str+1);
    printf("len : %d\n", ret);
 
    return 0;
    
}

输出如下:
:!g++ -Wall -g strlen.cpp -o strlen && ./strlen
len : 14
len : 14
--------------------- 
作者:zdl1016 
来源:CSDN 
原文:https://blog.csdn.net/zdl1016/article/details/8683418 
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://my.oschina.net/u/4000302/blog/3059803

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值