During the interview, the interviewer often asks for programs to be written. Based on the difficulty of the questions, the interviewer will have a different emphasis on algorithms and programming habits. For example, to write a memcpy function, the algorithm for this question is simple and clear, so the focus is on programming habits and engineering ideas.
The algorithm for this question is as follows:
0.1
[Cpp]
Void memcpy (void * dst, void * src, int count)
{
While (count --)
{
* Dst = * src;
Dst ++;
Src ++;
}
}
The problem is that void * cannot directly accumulate * dst = * src.
0.2
[Cpp]
Void memcpy (void * dst, void * src, int count)
{
Unsigned char * pdst = (unsigned char *) dst;
Unsigned char * psrc = (unsigned char *) src;
While (count --)
{
* Pdst = * psrc;
Pdst ++;
Psrc ++;
}
}
In a 32-bit system, what is the maximum memory that can be copied? Will the type be insufficient?
The original memory should not be modified for memory replication.
Therefore, the function declaration is modified as follows:
0.3
[Cpp]
Void memcpy (void * dst, const void * src, size_t count)
Is that all right?
What if a null pointer is passed in?
Modify it.
0.4
[Cpp]
Void memcpy (void * dst, const void * src, size_t count)
{
Assert (dst! = NULL );
Assert (src! = NULL );
Unsigned char * pdst = (unsigned char *) dst;
Const unsigned char * psrc = (const unsigned char *) src;
While (count --)
{
* Pdst = * psrc;
Pdst ++;
Psrc ++;
}
}
If such an array exists
Char ina [] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
Make the following calls:
Memcpy (& ina [1], & ina [0], 5 );
What will happen?
Because the original data and the target data overlap in the space, it is inevitable that the original data will be modified during the replication process. Such modifications are invisible in the function declaration (const void * src ). If you reduce the requirement, you can modify the original data to complete the replication. Can this design be implemented? Here is a version for your reference. However, such implementation makes the function unclear and can be considered as an exception.
Therefore
0.5
[Cpp]
Void memcpy (void * dst, const void * src, size_t count)
{
Assert (dst! = NULL );
Assert (src! = NULL );
Unsigned char * pdst = (unsigned char *) dst;
Const unsigned char * psrc = (const unsigned char *) src;
Assert (! (Psrc <= pdst & pdst <psrc + count); // determines whether there is overlap.
Assert (! (Pdst <= psrc & psrc <pdst + count ));
While (count --)
{
* Pdst = * psrc;
Pdst ++;
Psrc ++;
}
}
The implementation here is robust. Some people want to chain the call function, that is, after the memory is copied, the return value is directly used as a parameter of other functions.
[Cpp]
Void * memcpy (void * dst, const void * src, size_t count)
0.6. Therefore, the final version is
[Cpp]
Void * memcpy (void * dst, const void * src, size_t count)
{
Assert (dst! = NULL );
Assert (src! = NULL );
Unsigned char * pdst = (unsigned char *) dst;
Const unsigned char * psrc = (const unsigned char *) src;
Assert (! (Psrc <= pdst & pdst <psrc + count ));
Assert (! (Pdst <= psrc & psrc <pdst + count ));
While (count --)
{
* Pdst = * psrc;
Pdst ++;
Psrc ++;
}
Return dst;
}
Finally, some netizens conducted performance tests and concluded that the above implementation could not achieve the performance of library functions. I personally think that library functions may be optimized. For example, mmx technology is used to replicate one byte at a time to multiple bytes at a time.
This question appears too frequently during interviews. What can I describe if I can correctly write this function?
1. Lack of project experience, so the interview is well reviewed.
2. You may have a wealth of project experience.
3. I think there are many project experiences, but I did not pay attention to non-functional requirements. Waiting for a cup