1.strlen
字符串长度函数,不包括’\0’
int strlen(const char* str) {
assert(str != NULL);
int len = 0;
while ((*str++) != '\0') len++;
return len;
}
2.memset
void* memset(void* str, int value, size_t n) {
assert(str != NULL && n >= 0);
char* temp = (char*)str;
while (n--) *temp++ = value;
return str;
}
3.strcat
char* strcat(char* dest, const char* src) {
assert((dest != NULL) && (src != NULL));
char* res = dest;
while(*dest != '\0') dest++;
while(*src != '\0') *dest++ = *src++;
*dest = '\0';
return res;
}
4.strncat
char* strncat(char* dest, const char* src, size_t n) {
assert((dest != NULL) && (src != NULL));
assert(n >= 0);
char* res = dest;
while(*dest != '\0') dest++;
while(n-- && *src != '\0') *dest++ = *src++;
*dest = '\0';
return res;
}
5.strcpy
char* strcpy(char* dest, const char* src) {
assert((dest != NULL) && (src != NULL));
char* res = dest;
while ((*dest++ = *src++) != '\0');
return res;
}
6.strncpy
char* strncpy(char* dest, const char* src, size_t n) {
assert((dest != NULL) && (src != NULL));
char* res = dest;
while (n-- && (*dest++ = *src++) != '\0');
return res;
}
7.memcpy
(1)系统实现:没有考虑内存重叠
void* memcpy(void* dest, const void* src, size_t n) {
assert((dest != NULL) && (src != NULL) && (n >= 0));
char* pdest = (char*)dest;
const char* psrc = (char*)src;
while (n--) *pdest++ = *psrc++;
return dest;
}
(2)手写实现:要考虑内存重叠
void* memcpy(void* dest, const void* src, size_t n) {
assert((dest != NULL) && (src != NULL) && (n >= 0));
char* pdest = NULL;
const char* psrc = NULL;
if (src < dest && ((char*)src + n) > (char*)dest) {
// (1)dest和src重合,src在前面,dest在后面 => 从后往前复制
pdest = (char*)dest + n - 1;
psrc = (char*)src + n -1;
while (n--) *pdest-- = *psrc--;
} else {
// (1)dest和src重合,dest在前面,src在后面 (2)dest和src没有重合 => 从前往后复制
pdest = (char*)dest;
psrc = (char*)src;
while (n--) *pdest++ = *psrc++;
}
return dest;
}
8.memmove
系统实现:已经考虑内存重叠
void* memmove(void* dest, const void* src, size_t n) {
assert((dest != NULL) && (src != NULL) && (n >= 0));
char* pdest = NULL;
const char* psrc = NULL;
if (src < dest && ((char*)src + n) > (char*)dest) {
// (1)dest和src重合,src在前面,dest在后面 => 从后往前复制
pdest = (char*)dest + n - 1;
psrc = (char*)src + n -1;
while (n--) *pdest-- = *psrc--;
} else {
// (1)dest和src重合,dest在前面,src在后面 (2)dest和src没有重合 => 从前往后复制
pdest = (char*)dest;
psrc = (char*)src;
while (n--) *pdest++ = *psrc++;
}
return dest;
}
对比分析
(1)strcpy和memcpy
strcpy只能复制字符串;memcpy可以复制任意内容,例如字符数组、整型、结构体等。
strcpy不需要指定长度,遇到"\0"才结束,如果空间不够会引起内存溢出;memcpy通过参数指定复制长度。
strcpy不能复制包含’\0’的字符串;memcpy可以复制包含“\0”的字符串。
(2)memcpy和memmove
memcpy没有考虑内存重叠;memmove考虑内存重叠。