memset 、 memcpy 、 memmove 、 strcpy、 strlen
方法的实现整理。
在<string.h>头文件中声明的内存管理函数原型如下:
void *memcpy (void *, const void *, size_t);
:从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,参数分别为:(void *dest, void *src, size_t n),将src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。void *memset (void *, int, size_t);
:在一段内存块中填充某个给定的值,参数分别为:(void *s, int ch, size_t n),将s中当前位置后面的n个字节用ch替换并返回s。它是对较大的结构体或数组进行清零操作的一种最快方法。void *memmove (void *, const void *, size_t);
:拷贝字节,如果目标区域和源区域有重叠的话,能够保证源在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改,参数分别为:(void* dest, const void* src, size_t count),由src所指内存区域复制count个字节到dest所指内存区域。当目标区域与源区域没有重叠则和memcpy函数功能相同。
在<string.h>头文件中声明的字符串处理函数原型如下:
char *strcpy (char *, const char *);
:把含有’\0’结束符的字符串复制到另一个地址空间,参数分别为:(char* dest, const char *src),把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间。size_t strlen (const char *)
:计算给定字符串的长度,不包括’\0’在内。
函数功能的实现
1. memcpy
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
这样实现存在的一个问题是,如果dest指针所指的区域和src指针所指的区域重叠的话,函数功能不能正确执行,所以会使用restrict
关键字来限定这两个参数,void *memcpy( void * restrict dest , const void * restrict src, size_t n)
。改进思路:可先进行地址对齐后,按照CPU字长进行拷贝。
2. memmove
void *memmove(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
if (dest <= src || dest >= (src + count))
{
while (count--)
*tmp++ = *s++;
}
else
{
tmp += count;
s += count;
while (count--)
*--tmp = *--s;
}
return dest;
}
memmove
在copy两个有重叠的内存时能正确执行,且memcpy
比memmove
的速度要快一些。
3. memset
void *memset(void *dest, int ch, size_t n)
{
char *tmp = dest;
while (n--)
*tmp++ = ch;
return dest;
}
1. strlen
size_t strlen(const char *s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
;
return (sc - s);
}
如上单字符的计算效率太低,改进思路1:从字符串的两端同时开始计算。
2. strcpy
char *strcpy(char *dest, const char *src)
{
char *tmp = dest;
while (*tmp++ = *src++ != '\0')
;
return dest;
}
改进后的实现:
#include <stddef.h>
char *strcpy(char *dest, const char *src)
{
register char c;
char *s = src;
const ptrdiff_t off = dest - src - 1;
do
{
c = *s++;
s[off] = c;
} while (c != '\0');
return dest;
}
References:
- https://baike.baidu.com/item/memcpy
- https://blog.csdn.net/c1204611687/article/details/85864924
- https://blog.csdn.net/c1204611687/article/details/85849467