Strlen glibc source code analysis

Source: Internet
Author: User

Size_t <br/> strlen (str) <br/> const char * str; <br/>{< br/> const char * char_ptr; <br/> const unsigned long int * longword_ptr; <br/> unsigned long int longword, himagic, lomagic; <br/>/* Handle the first few characters by reading one character at a time. <br/> Do this until CHAR_PTR is aligned on a longword boundary. */<br/> for (char_ptr = str; (unsigned long int) char_ptr <br/> & (sizeof (long Word)-1 ))! = 0; <br/> ++ char_ptr) <br/> if (* char_ptr = '/0') <br/> return char_ptr-str; <br/>/* All these elucidatory comments refer to 4-byte longwords, <br/> but the theory applies equally well to 8-byte longwords. */<br/> longword_ptr = (unsigned long int *) char_ptr; <br/>/* Bits 31, 24, 16, and 8 of this number are zero. call these bits <br/> the "holes. "Note that there is a hole just to the left Of <br/> each byte, with an extra at the end: <br/> bits: 01111110 11111110 11111110 11111111 <br/> bytes: aaaaaaaa bbbbbbbb cccccccc dddddddd <br/> The 1-bits make sure that carries propagate to the next 0-bit. <br/> The 0-bits provide holes for carries to fall. */<br/> himagic = 0x80808080L; <br/> lomagic = 0x01010101L; <br/> if (sizeof (longword)> 4) <br/> {<br/>/* 64-bit version of t He magic. */<br/>/* Do the shift in two steps to avoid a warning if long has 32 bits. */<br/> himagic = (himagic <16) <16) | himagic; <br/> lomagic = (lomagic <16) <16) | lomagic; <br/>}< br/> if (sizeof (longword)> 8) <br/> abort (); <br/>/* Instead of the traditional loop which tests each character, <br/> we will test a longword at a time. the tricky part is testing <br/> if * any Of the four * bytes in the longword in question are zero. */<br/> for (;) <br/>{< br/> longword = * longword_ptr ++; <br/> if (longword-lomagic) &~ Longword & himagic )! = 0) <br/>{< br/>/* Which of the bytes was the zero? If none of them were, it was <br/> a misfire; continue the search. */<br/> const char * cp = (const char *) (longword_ptr-1); <br/> if (cp [0] = 0) <br/> return cp-str; <br/> if (cp [1] = 0) <br/> return cp-str + 1; <br/> if (cp [2] = 0) <br/> return cp-str + 2; <br/> if (cp [3] = 0) <br/> return cp-str + 3; <br/> if (sizeof (longword)> 4) <br/>{< br/> if (cp [4] = 0) <br/> return cp-str + 4; <br/> if (cp [5] = 0) <br/> return cp-str + 5; <br/> if (cp [6] = 0) <br/> return cp-str + 6; <br/> if (cp [7] = 0) <br/> return cp-str + 7; <br/>}< br/>} 

 

The main idea is to convert a character that reads one byte into a string that reads 4/8 bytes each time, improving the efficiency.

 

Judge whether the character is 0 one by one. If the character is 0, exit. The code is concise, and the performance is not low. It is a little inadequate. On a computer with a 4-byte or 8-byte length
Reading one byte is a waste of computer capabilities. If you read four or eight bytes each time, the total number of reads will be greatly reduced. When you read four or eight bytes
If the address is not on the boundary, the machine will have to read it twice. This will reduce the performance and weaken the optimization effect. Therefore, the first few characters must be processed separately.
Read 4 or 8 bytes each time starting from the long boundary address.


Method:

1. The first several bytes are processed separately.

For (char_ptr = str; (unsigned long int) char_ptr <br/> & (sizeof (longword)-1 ))! = 0; <br/> ++ char_ptr) <br/> if (* char_ptr = '/0') <br/> return char_ptr-str;
2. 4-byte or 8-byte processing in the middle


3. If there is zero in the middle, it will be processed separately.

If (longword-lomagic )&~ Longword & himagic )! = 0) <br/>{< br/>/* Which of the bytes was the zero? If none of them were, it was <br/> a misfire; continue the search. */<br/> const char * cp = (const char *) (longword_ptr-1); <br/> if (cp [0] = 0) <br/> return cp-str; <br/> if (cp [1] = 0) <br/> return cp-str + 1; <br/> if (cp [2] = 0) <br/> return cp-str + 2; <br/> if (cp [3] = 0) <br/> return cp-str + 3; <br/> if (sizeof (longword)> 4) <br/>{< br/> if (cp [4] = 0) <br/> return cp-str + 4; <br/> if (cp [5] = 0) <br/> return cp-str + 5; <br/> if (cp [6] = 0) <br/> return cp-str + 6; <br/> if (cp [7] = 0) <br/> return cp-str + 7; <br/>}< br/>} 

 

 


It looks good, but there is another problem: how to ensure that all 0 bytes exist when reading 4 or 8 bytes, because 0 is used to indicate the end of the string.
The key to optimization is to determine whether all 0 bytes exist in several consecutive bytes. We cannot judge one byte or one byte, because the optimization idea is to read
Multiple bytes to reduce the total number of reads. If you judge each byte separately, the optimization will be lost.

What should we do? Of course, bit operations are considered first.

* What are the characteristics of a pure 0 byte? Obviously, every bit is 0, and every bit is 1 after bitwise inversion.
* What are the other features of a zero-byte? This byte minus 1, must borrow 1 from a higher byte. After borrowing 1, the maximum bit of this Byte must be 1.

Taking the 4-byte integer n as an example, we only need to subtract 1 from each byte. If a pure 0 byte exists, there will inevitably be a bits.
The maximum byte value is 1. You only need to determine whether the maximum bit of each byte exists 1. However, there is another problem: In this 4-byte integer,
Some bytes may have a maximum of 1, so these bytes must be excluded.

Solution:

* Subtract 1 from each byte of n and get the highest bit to get x. If there is a borrow bit, the highest bit of this byte is 1.
* Reverse each byte of n and retrieve the highest bit. The highest bit of y and y is 1, indicating that it is 0 in n.
* Bitwise and operation of x and y. If the value is not equal to 0, it means that n has at least 1 byte. The original highest bit is not 1, and then it becomes 1, that is, the borrow bit.

If n contains all 0 bytes, x & y must not be 0, because the maximum bit of the borrowed byte will be set to 1.
If n does not contain all 0 bytes, no borrow space is generated. x & y is equal to 0.
X & y = (n-0x01010101 )&~ N & amp; 0x80808080

 

Reference: http://topic.csdn.net/u/20091029/18/8f047493-15f8-4af5-bb8d-b5147128f79a.html

Http://simohayha.javaeye.com/blog/439059

Http://bigwhite.blogbus.com/logs/37753065.html

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.