[Read Source Code] view strcpy implemented in libc

Source: Internet
Author: User

[Read Source Code] view strcpy implemented in libc

 

This libc is the choice of dietlibc-0.32, is a boss introduced, said to be relatively simple for learning to use only. After reading the big call when ....(CodeI personally think it is bad)

Why is this strcpy? There is a slight reason:
1. The exam is almost mandatory. The standard answer given by the exam is weird ....
2. This strcpy provides two implementations. The efficiency of the second implementation is even higher than the strcpy of the compilation Implementation of vc9. My rough estimate is 30% higher.
This greatly attracted my attention:-D (nnd, whichProgramMembers do not want their programs to run fast)
3. Let's take a look at how other people's code is written.

Note that the libc code source seems complicated, including from BSD, GNU, and some other... (hodgedge % >_<%)
OK, the Code is as follows:

 

# Define unaligned (x, y) (unsigned long) X & (sizeof (unsigned long)-1) ^ (unsigned long) Y & (sizeof (unsigned long) -1) # define stralign (x) (unsigned long) X & 3 )? 4-(unsigned long) X & 3): 0) # define mkw (x) (X | x <8 | x <16 | x <24) # define GFC (x) & 0xff) # define incstr (x) do {x >>=8 ;}while (0 ); char * strcpy (char * S1, const char * S2) {char * res = S1; # ifdef want_small_string_routines while (* S1 ++ = * S2 ++ )); return (RES); # else int TMP; unsigned long l; If (unaligned (S1, S2) {While (* S1 ++ = * S2 ++ )); return (RES);} If (TMP = stralign (S1) {While (TMP --&& (* S1 ++ = * S2 ++); If (TMP! =-1) Return (RES);} while (1) {L = * (const unsigned long *) S2; If (L-mkw (0x1ul ))&~ L) & mkw (0x80ul) {While (* S1 ++ = GFC (L) incstr (l); Return (RES);} * (unsigned long *) s1 = L; S2 + = sizeof (unsigned long); S1 + = sizeof (unsigned long) ;}# endif}

 

I also gave the macros I needed, which looks nice.
Let's take a look at this simple implementation: want_small_string_routines
While (* S1 ++ = * S2 ++ ));
Return (RES );
Just two lines of code are simple enough.

Let's look at the subsequent implementation. I don't want to look at the judgment of the previous two macros. It seems that it is a four-byte alignment judgment. I guess it...
Really interesting here while (1) Here, this is the key to the problem.
Debug several times to know whether the string contains '\ 0' in the IF statement '.
If '\ 0' is included, use while to copy the remaining strings;
If '\ 0' is not included, long is used for copying because four bytes can be copied at a time.
When the if statement is out, everyone knows what it means. The problem lies in it. In this case, you can guess to copy the remaining (less than four bytes) strings.
Let's take a look:
While (* S1 ++ = GFC (L) incstr (L );
Return (RES );
These two statements of code.
While (* si ++ = getfirstchar (L) // obtain the first character of L
Inc_str (l); // offset one byte later

So how does he determine whether there is '\ 0' in this long? The key to the problem lies in
(L-mkw (0x1ul ))&~ L) & mkw (0x80ul)
In this Code!
This code is hard to understand. It took a long time for me to understand. OK. How do you determine whether a byte is 0?
You may use = 0, but this code can only be valid for one byte. This libc uses a complicated method:
Byte I;
(I-0x1 )&~ I) & 0x80
He made such a decision.
That code can be written in this way (I-1) & (0xff-i) & 0x80, we can draw a table to understand what is going on.

I 0 1 2... 127 128 129 253... 254 255
I-1 255 0 1... 126 127 128 252... 253 254
255-i 255 254 253... 128 127 126... 2 1 0
& Amp; 255 <= 0 <= 1... <= 126 <= 127 <= 126... <= 2 <= 1 <= 0

There is a proposition, N> = m, SO (N & M) <= m is bound to be true. (who can help prove it? ^_^)
So (I-1) & (255-i) inside the largest number, it is expected that the middle of the several, it is a pity
127 & 127 = 127 <128 = 0x80
So he uses thisAlgorithmTo determine whether a byte is '\ 0', that is, 0.
If it is 0, 255 is returned; otherwise, 0 is returned.
There are four bytes in a long string. If there is a byte that shows 0, that is, the string Terminator, it will be the expression that turns into a non-zero number, so that his goal is achieved.

Okay. Let's review how he did it?
1. read four bytes to form a long
2. Check whether the long contains the terminator '\ 0' of the c string'
3. if it contains, copy by byte
4. If it is not included, press long to copy
5. Return to 1

Very sharp, but I thought of a problem when I went to bed last night.
1. I have read FreeBSD's strcpy, which is implemented in FreeBSD's libkern.
2. The strcpy of VC is implemented by Assembly. When possible, Ms may limit the optimization program.
Why don't they use this algorithm ??
Let's take a look at how strcpy is implemented in FreeBSD:

 

 
Char * strcpy (char * _ restrict to, const char * _ restrict from) {char * save = to; For (; (* To = * From ); ++ from, ++ to); Return (SAVE );}

 

This code is very different from the strcpy of MS, but the efficiency is not much different. At least it will not be 30% different. That is to say, the compilation of MS is the same as that of FreeBSD's algorithm.
They all choose to read one byte!
What is the problem with the strcpy implemented by libc ??
When he reads four bytes at a time, the space occupied by the string may not always be a multiple of four. Therefore, this will cross the border !!! It may be that your program is down ....
Verify:
Char SRC [4] = {1, 0, 1, 1 };
Char Dest [10] = {0 };
Strcpy (DEST, Src );
Then try the next breakpoint to see if the value of Long is 0x01010001.
Therefore, the efficiency of this algorithm is very high, and it is actually unreliable.

PS:
1. dietlibc-0.32 in the string. h, there are several functions are implemented using this algorithm
2. dietlibc-0.32 code style is very bad, compared with FreeBSD, S1, S2 such a name... sometimes it is difficult to understand %> _ <%
3. The efficiency of the underlying database is important, but correctness is a prerequisite.
4. Another question: Will new char [1] and malloc (1) allocate four bytes to me? There should be no similar saying about standards!

 

PS:

Go back and read the c99 document, which is described as follows:

The malloc function allocates space for an objectWhose size is speci partitioned ed by sizeAndWhose value is indeterminate.

Therefore, I plan to maintain my previous judgment. This may cross the border, because his assumptions are not necessarily true.

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.