/* 下面是库函数中strlen的实现,比想像的要复杂 */
size_t strlen (str)
const char *str;
{
const char *char_ptr;
const unsigned long int *longword_ptr;
unsigned long int longword, himagic, lomagic;
for (char_ptr = str; ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;
++char_ptr)
if (*char_ptr == '\0')
return char_ptr - str;
longword_ptr = (unsigned long int *) char_ptr;
himagic = 0x80808080L;
lomagic = 0x01010101L;
/* Instead of the traditional loop which tests each character,
we will test a longword at a time. The tricky part(棘手的部分) is testing
if *any of the four* bytes in the longword in question are zero. */
for (;;)
{
longword = *longword_ptr++;
if (((longword - lomagic) & ~longword & himagic) != 0)
{
/* 关键在于如果有0,就一定要测试出来,误判没关系 */
/* 只是读,并没有写,不会出现段错误 */
const char *cp = (const char *) (longword_ptr - 1); /* 减一是因为前面已经加了1 */
if (cp[0] == 0)
return cp - str;
if (cp[1] == 0)
return cp - str + 1;
if (cp[2] == 0)
return cp - str + 2;
if (cp[3] == 0)
return cp - str + 3;
if (sizeof (longword) > 4)
{
if (cp[4] == 0)
return cp - str + 4;
if (cp[5] == 0)
return cp - str + 5;
if (cp[6] == 0)
return cp - str + 6;
if (cp[7] == 0)
return cp - str + 7;
}
}
}
}
思路:1. 不是用判断每一个字节是否为'\0'的方法在确定字符串的长度
2. 采用的是一次判断四个字节也就是一个int的方法来确定字符串的长度
3. if (((longword - lomagic) & ~longword & himagic) != 0)用于判断四个字节中是否有一个字节为0,如果有某个字节为0,则if条件为真
4. 当确定四个字节中有一个字节为0后,就逐个比较每个字节,来确定为0的那个字节的位置
注意:
1. 在以4个字节为单位判断之前,要保证以4字节对齐(也就是int),因此第一个for的作用就是一个确保四字节对齐,对对齐之前,要一个字节一个字节判断
2. 计算机本身对有符号数和无符号数的加减法的处理都是统一按照补码进行,没有区别,但乘除法不同