函数实现-memcpy-strcpy-memmove-memset
1. 函数原型(c++ reference)
void * memcpy ( void * destination, const void * source, size_t num ); 不能解决某些覆盖问题。
char * strcpy ( char * destination, const char * source ); 不能解决某些覆盖问题,根据'\0'表示字符串复制终止。
void * memmove ( void * destination, const void * source, size_t num ); 能够解决所有覆盖问题。
void * memset ( void * ptr, int value, size_t num ); 其中value使用int传入,但是被解释为unsigned char。
2. 重叠问题
·dest == src 不需要拷贝
·dest<src,无论有没有重叠,正向拷贝即可。
·dest>src,且dest>=src+len,没有重叠,正向拷贝即可。
·dest>src,且dest<src+len,有重叠,需要逆向拷贝。
对于memcpy和strcpy,都是正向拷贝,不能处理第四种情况。
对于memmove,考虑到所有的情况即可。
对于memset,相对简单,就是赋值就可以了。
3. 代码
assert((dest != NULL) && (src != NULL) && (dest!=src)); // assert
char* p_dest = (char*)dest; // copy
const char* p_src = (const char*)src;
while(num-- > 0)
*p_dest++ = *p_src++;
return dest; // address
}
char* strcpy(char* dest, const char* src) {
assert((dest!=NULL) && (src!=NULL) && (dest!=src));
char* address = dest;
while((*dest++ = *src++) != '\0')
NULL;
return address;
}
void* memmove(void* dest, const void* src,size_t num) {
assert((dest!=NULL) && (src!=NULL) && (dest!=src));
char* p_dest = (char*)dest;
const char* p_src = (const char*)src;
if(p_dest>p_src && p_dest<p_src+num) { //p_dest>p_src,逆向拷贝
p_dest += num - 1;
p_src += num - 1;
while(num--)
*p_dest-- = *p_src--;
}
else { //p_dest<=p_src,此时无论是否重叠都可以使用正向拷贝
while(num--)
*p_dest++ = *p_src++;
}
return dest;
}
void* memset(void* dest, int value, size_t num) {
assert(dest != NULL);
unsigned char* p_dest = (unsigned char*)dest;
while(num-- > 0)
*p_dest++ = (unsigned char)value;
return dest;
}
4. 其他
这几个函数常被用来测试编程人员的编程风格。实际上,函数库中的这些函数实现都是汇编搞定的,要更多的考虑机器指令方面的问题,来使用汇编,效率会更高,这就先到这里了。
5. 关于size_t
size_t是标准C库中定义的,应为unsigned int。 实际上,对于本文的一系列函数,msdn的函数原型都是用size_t,而linux内核往往使用int。
原因如下吧:
“数据类型"socklen_t"和int应该具有相同的长度。否则就会破坏 BSD套接字层的填充.POSIX开始的时候用的是size_t, Linus Torvalds(他希望有更多的人,但显然不是很多) 努力向他们解释使用size_t是完全错误的,因为在64位结构中 size_t和int的长度是不一样的,而这个参数(也就是accept函数的第三参数)的长度必须和int一致,因为这是BSD套接字接口标准.最终POSIX的那帮家伙找到了解决的办法,那就是创造了一个新的类型"socklen_t".Linux Torvalds说这是由于他们发现了自己的错误但又不好意思向大家伙儿承认,所以另外创造了一个新的数据类型 。
在C++中,size_t的引入增强了程序在不同平台上的可移植性,经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。”
6. 参考资料
C++ Reference http://www.cplusplus.com/reference/clibrary/cstring/
strcpy()、memcpy()、memmove()、memset()的实现 http://www.cnitblog.com/guopingleee/archive/2009/02/15/54581.html
size_t 百度百科 http://baike.baidu.com/view/3236587.htm