Strcpy and strncpy

Source: Internet
Author: User

 

Library Function extern char * strcpy (char * DEST, char * SRC)

Usage: # include <string. h>

Function: Copies the string ending with null indicated by Src to the array indicated by DeST.

Note: The memory areas specified by Src and DEST cannot overlap and DEST must have sufficient space to accommodate SRC strings.
Returns the pointer to DeST.

NOTE: If strcpy is not met with/0, it will not be copied. After the copy is complete, determine whether the final character is '/0'. If yes, exit the loop!

That is to say, DEST has an ending sign '/0!


It is known that the prototype of the strcpy function is:
Char * strcpy (char * strdest, const char * strsrc );
1. Implement the strcpy function without calling the library function.
2. Explain why char * is returned *.

Explanation:
1. Implementation Code of strcpy
 

Char * strcpy (char * DEST, const char * SRC ){

Assert (DEST! = NULL) & (SRC! = NULL ));

Char * TMP = DEST;

While (* TMP ++ = * SRC ++ )! = '/ 0' )

/* When the loop ends * the Dest is '/0'. You do not need to manually add the end mark */

/* Nothing */;

Return DEST;

}

Incorrect practice:
[1]
(A) if the pointer is not checked, it means that the respondent does not pay attention to the robustness of the Code.
(B) used to check the pointer validity ((! Strdest) | (! Strsrc) or (! (Strdest & strsrc). It indicates that the respondent has no deep understanding of implicit conversions of types in C language. In this example, char * is converted to bool, that is, implicit type conversion. Although this function is flexible, it is more likely to increase the error probability and increase the maintenance cost. Therefore, C ++ adds the bool, true, and false keywords to provide a safer conditional expression.
(C) Use (strdest = 0) | (strsrc = 0) to check the pointer validity. This means that the respondent does not know the benefit of using constants. Directly Using a literal constant (such as 0 in this example) reduces the maintainability of the program. 0 is simple, but there may be a lot of pointer checks in the program. In case of PEN mistakes, the compiler cannot find that the generated program contains logical errors and it is difficult to eliminate them. If null is used to replace 0, the compiler will check if a spelling error occurs.
[2]
(A) return new string ("invalid argument (s)"); it indicates that the respondent does not know the purpose of the returned value, and is not cautious about memory leakage. Returning the memory allocated in the function body from the function is very dangerous. It throws the obligation to release the memory to an uninformed caller. In most cases, the caller will not release the memory, which leads to memory leakage.
(B) Return 0;, indicating that the respondent did not master the exception mechanism. The caller may forget to check the return value, and the caller may not be able to check the return value (see the chain expression below ). If you want the return value to shoulder the dual function of returning the correct value and abnormal value, the result is often invalid in both functions. The return value should be replaced by throwing an exception, which can reduce the burden on the caller, prevent errors from being ignored, and enhance the maintainability of the program.
[3]
(A) if you forget to save the original strdest value, it means that the answer provider's logic is not strict.
[4]
(A) cyclically write it as while (* strdest ++ = * strsrc ++);, same as [1] (B ). In Linux, this is exactly how it is implemented !!??
(B) cyclically write while (* strsrc! = '/0') * strdest ++ = * strsrc ++;, indicating that the respondent does not check the boundary conditions effectively. After the loop body ends, '/0' is not correctly added to the end of the strdest string '.

2. Return the original strdest value to enable the function to support chained expressions, increasing the "added value" of the function ". Functions of the same function are naturally more ideal if they can reasonably improve availability.
The form of a chained expression is as follows:
Int ilength = strlen (strcpy (stra, strb ));
Another example:
Char * stra = strcpy (New char [10], strb );
The original strsrc value is returned incorrectly. First, the source string must be known and it does not make sense to return it. Second, the expression in the second example cannot be supported. Third, to protect the source string, the const uses const to limit the content referred to by strsrc and returns const char * as char *. If the type is different, an error is returned during compilation.

The definition in Linux is as follows:
/Usr/lib/string. h


 string.h:
char *strcpy (char *__restrict __dest, __const char *__restrict __src)
     __THROW;

/Usr/src/linux-2.6.0-test3/lib/string. C.


/**
 * strcpy - Copy a %NUL terminated string
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 */
char * strcpy(char * dest,const char *src)
{
        char *tmp = dest;

        while ((*dest++ = *src++) != '/0')
                /* nothing */;
        return tmp;
}

In string. H, the macro _ Throw exists. Let's see where the macro is defined:
$ Grep _ Throw/usr/include/*. H | grep define


...
usr/include/malloc.h:#  define __THROW throw ()
...

In addition, almost every pre-processing command is processed by _ Throw. You can view it as follows:
$ Grep-R _ Throw/usr/include/* | grep "#"

Linux is the same as high-quality C/C ++, except for exception handling.

 

Strncpy implementation in kernel linux-2.6.22/lib/string. c

 

Char * strncpy (char * DEST, const char * SRC, size_t count)
{
Char * TMP = DEST;

While (count ){
If (* TMP = * SRC )! = 0)
SRC ++;
TMP ++;
Count --;
}/* Warning :!!! End of DeST not set: '/0 '!!! */
Return DEST;
}

Note the differences between strcpy and strncpy in Linux:

Strcpy: While (* DEST ++ = * SRC ++ )! = '/0 ')

/* When the operation ends, * the value of DeST is '/0', and the end mark is already in place. */

Strncpy: If (* TMP = * SRC )! = 0)/* Why can I use 0 to determine ??? */

/* When the runtime ends, * the TMP value is uncertain and may not necessarily have an ending sign (if the Count parameter is smaller than the SRC Character Count ), in this way, TMP will always be read to '/0' in the memory. */

Why does strlen (TMP) of this Code return 6?

# Include <stdio. h>
# Include <stdio. h>
# Include <string. h>

Char * strncpy_1 (char * DEST, const char * SRC, size_t count)
{
Char * TMP = DEST;

While (count)
{

If (* TMP = * SRC )! = '/0 ')
{

SRC ++;
TMP ++;

}

Count --;

}

If (* TMP! = '/0 ')
* ++ TMP = '/0 ';
 
Return DEST;
}

Void print (char * Ch)
{
Char * TMP;

For (TMP = CH; * TMP! = '/0'; TMP ++)
Printf ("% C", * TMP );
Printf ("/N ");
}

Int main (void)
{
Char * TMP;
Char SRC [] = "Hello, world! ";
Char Dest [20];

Printf ("the length of SRC is: % d/N", strlen (SRC ));

Printf ("the source string is:/t ");
Print (SRC );
 
TMP = strncpy_1 (DEST, SRC, 5 );

Printf ("the destination string is:/t ");
Print (TMP );

Printf ("the length of DeST is: % d/N", strlen (TMP ));

Return 0;
 
}

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.