目录
1)memcpy
函数声明:void *memcpy(void *dst, const void *src, size_t n); // //dst:目的地址, src:源地址 n:要拷贝的字节数
但是标准memcpy(),对于地址重叠的情况,该函数的行为是未定义的。//If copying takes place between objects that overlap, the behavior is undefined.
但是面试时,手写memcpy()时就需要考虑地址重叠的情况。
另外,标准库也提供了地址重叠时的内存拷贝函数:memmove(),那么为什么还要考虑重写memcpy()函数呢?
因为memmove()函数的实现效率问题,该函数把源字符串拷贝到临时buf里,然后再从临时buf里写到目的地址,增加了一次不必要的开销。
//dst:目的地址, src:源地址 count:要拷贝的字节数
void* memcpy(void* dst, const void* src, size_t count)
{
// 输入判断
if(dst==src || count==0)
return dst;
if(dst==nullptr || src==nullptr)
return nullptr;
char *pdst = (char *)dst;
char *psrc = (char *)src;
int cnt = count;
// 内存拷贝
if (pdst > psrc && pdst < (psrc + count)) // 自后向前(目标地址比源地址比原地址高且与源空间重叠,如果自前向后拷贝会覆盖掉目标地址前面的内容)
{
pdst += (cnt -1);
psrc += (cnt -1);
while (cnt--)
{
*pdst-- = *psrc--;
}
}
else // 自前向后
{
while (cnt--)
{
*pdst++ = *psrc++;
}
}
return dst;
}
2)strcpy
//没有考虑重叠版本
char* strcpy(char *dst,const char *src)
{
// 宏函数,条件为假 输出括号里的信息,并终止程序
assert(dst != nullptr&&src != nullptr);
char *cur = dst;
while((* cur++ = * src++) != '\0')
;
return dst;
}
//考虑重叠
char* strcpy(char* dst, const char* src)
{
assert((dst != NULL) && (src != NULL));
if(dst==src)
return dst;
char* cur = dst;
int size = strlen(src) + 1;
if(cur > src && cur < src + len)
{
cur = cur + size - 1;
src = src + size - 1;
while(size--)
{
*cur-- = *src--;
}
}
else
{
while(size--)
{
*cur++ = *src++;
}
}
return dst;
}
3) memset
void* memset(void *dst, int val, size_t size) {
char *s_dst = dst;
char ch = val;
if (s_dst == NULL) {
return NULL;
}
while (size--) {
*s_dst++ = ch;
}
return dst;
}
4)strcat
char* strcat(char* dst, const char* src)
{
char* ret = dst;
while(*dst != '\0')
++dst;
while((*dst++ = *src++) != '\0');
return ret;
}
5)strcmp
基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数
int strcmp(const char* str1, const char* str2)
{
while(*str1 == *str2 && *str1 != '\0')
{
++str1;
++str2;
}
return *str1 - *str2;
}