I. Usage and precautions of strcpy
1) strcpy () Overview
Prototype: extern char * strcpy (char * DEST, char * SRC); // pay attention to who will copy it
Usage: # include <string. h>
Function: Copies the string ending with null in SRC to the array in DeST.
Note: The memory areas specified by Src and DEST cannot overlap and DEST must have enough space to hold SRC strings. A pointer to DEST is returned.
For example, char a [100], B [50];
Strcpy (A, B );
For example, use strcpy (B, A). Pay attention to whether the string length (before the first '\ 0') in a exceeds 50 bits. Otherwise, the memory address of B may overflow.
2) instance resolution
If the following code is available, what is the output?
#include "stdio.h" #include <string.h> intmain() { char dest[3]; char str[6]="Hello"; strcpy(dest,str); printf("%s\n",dest); }
The compilation output is as follows: Hello // No output garbled characters. Why is this strange?
Analysis:
The length of the string in STR is greater than the Memory Length of DeST 3. Why can the STR string still be copied to DEST?
Let's take a look at the source code implementation of strcpy:
Char * strcpy (char * strdest, const char * strsrc) {assert (strdest! = NULL) & (strsrc! = NULL) // determines whether the pointer is valid, that is, the memory is allocated, pointing to a certain block to determine the region char * address = strdest; // remember the starting value of the target address while (* strdest ++ = * strsrc ++ )! = '\ 0') // first copy and then judge, so you do not need to add null after the copy is complete; // * strdest =' \ 0 '; --> adds an ending character. because the string has been copied. return address; // return the value of the destination first address. }
From the code above, we can see that the strcpy function assumes that the memory space of strdest is sufficient to put down the content of strsrc. that is to say, when using the strcpy function, you should make (strdest memory space)> = (strsrc memory space)
When strcpy (DEST, STR); is called, while (* strdest ++ = * strsrc ++ )! = '\ 0') instead of determining whether the strdest memory is sufficient, it directly copies the content of srtsrc to the strdest, and ends when it is copied to' \ 0.
Therefore, when printf ("% s \ n", DEST); is used, the output stops when '\ 0' is encountered. Therefore, the output is hello.
Although the correct results are output, memory overflow errors may occur.
3) high-frequency questions in the written examination and interview
1> implement the strcpy function without calling the library function.
2> explain why char * is returned *.
Question 1> answer:
Implementation Code of strcpy
char * strcpy(char * strDest,const char * strSrc) { if((strDest==NULL)||(strSrc==NULL)) //[1] throw "Invalid argument(s)"; //[2] char *strDestCopy=strDest; //[3] while((*strDest++=*strSrc++)!='\0'); //[4] return strDestCopy; }
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 ("invalidargument (s)"); it indicates that the respondent does not know the purpose of the returned value, and is not cautious about memory leakage. It is very dangerous to return the memory allocated in the function body from the function. The obligation to release the memory is sent to the 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 ).
(B) cyclically write while (* strsrc! = '\ 0') * strdest ++ = * strsrc ++; this indicates that the respondent does not check the boundary condition effectively. After the loop body ends, '\ 0' is not correctly added to the end of the strdest string '.
Question 2> answer:
Returns 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: intilength = 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.
Ii. Differences between memset, memcpy, and strcpy
1) memset
Prototype: extern void * memset (void * buffer, int C, int count );
Usage: # include <string. h> or <memory. h>
Function: sets the first count byte of the memory area referred to by buffer to character C.
Note: The pointer to the buffer is returned. It is used to set all the memory space to a certain character.
For example:
Char A [10];
Memset (A, '\ 0', sizeof ());
Memset can easily clear a variable or array of the structure type.
For example, struct _ test {char s [10];
Int X;
Int y;
};
Variable struct _ test st;
1) the general method of clearing the st is as follows: St. s [0] = '\ 0'; ST. x = 0; ST. Y = 0;
2) use memset as follows: memset (& St, 0, sizeof (struct_test ));
Array: struct _ test st [10];
Memset (St, 0, sizeof (struct _ test) * 10); // clearing method
1> memset source code implementation C Language
#include <mem.h> void* memset(void* s, int c, size_t n){ unsigned char* p = (unsigned char*) s; while (n > 0) { *p++ = (unsigned char)c; --n; } return s;}
2> example:
#include "string.h"#include "stdio.h"int main(){ charbuffer[] = "Hello world\n"; printf("Bufferbefore memset: %s\n", buffer); memset(buffer,'*', strlen(buffer) ); printf("Bufferafter memset: %s\n", buffer); return0;}
2) memcpy
Prototype: extern void * memcpy (void * DEST, void * SRC, unsigned int count );
Usage: # include <string. h>
Function: copy count bytes from the memory area indicated by Src to the memory area indicated by DeST.
Note: SRC and DEST indicate that the memory areas cannot overlap. The function returns a pointer to DeST. You can copy any data type object.
For example, char a [10], B [5];
Memcpy (B, A, sizeof (B);/* Note that if sizeof (a) is used, memory address overflow of B */
Iii. Differences
The main application of memset is to initialize a memory space.
Memcpy is used to copy data from the source space to the target space.
Strcpy is used for string copy. When '\ 0' is encountered, it will end.
Instance:
For example, memcpy is used when initializing a space.
Int M [100]
Memset (void *) m, 0x00, sizeof (int * 100); // OK!
Memcpy (void *) M, "\ 0 \ 0 \ 0 \ 0...", sizeof (INT) * 100); // notok
Memset is used to set all memory spaces to a specific character. It is generally used to initialize the defined string to ''or '\ 0 ';
Example: Char A [100]; memset (A, '\ 0', sizeof ());
Memcpy is used for memory copying. It can be used to copy objects of any data type and can specify the length of the copied data;
For example, char a [100], B [50]; memcpy (B, A, sizeof (B); // Note: If sizeof (a) is used ), it will cause memory overflow (sizeof (B) is the number of copies)