memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。
但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。
memmove的处理措施:
(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
-- memcpy实现
1
2
3
4
5
6
7
8
|
void
*
memcpy
(
void
* dest,
const
void
* src,
size_t
n)
{
char
* d = (
char
*) dest;
const
char
* s = (
const
char
*) src;
while
(n-–)
*d++ = *s++;
return
dest;
}
|
-- memmove实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
void
*
memmove
(
void
* dest,
const
void
* src,
size_t
n)
{
char
* d = (
char
*) dest;
const
char
* s = (
const
char
*) src;
if
(s>d)
{
// start at beginning of s
while
(n--)
*d++ = *s++;
}
else
if
(s<d)
{
// start at end of s
d = d+n-1;
s = s+n-1;
while
(n--)
*d-- = *s--;
}
return
dest;
}
|
示意图:
(1)内存低端 <-----s-----> <-----d-----> 内存高端 start at end of s
(2)内存低端 <-----s--<==>--d-----> 内存高端 start at end of s
(3)内存低端 <-----sd-----> 内存高端 do nothing
(4)内存低端 <-----d--<==>--s-----> 内存高端 start at beginning of s
(5)内存低端 <-----d-----> <-----s-----> 内存高端 start at beginning of s
strcat源码
123456789101112131415161718/***
*char *strcat(dst, src) - concatenate (append) one string to another
在C里面,0为假,非0为真。对于while( *cp++ = *src++ )来说,什么时候结束循环就要看*cp++ = *src++表达式的值什么时候为0,赋值表达式的值为=运算符左值的值,当*src遇到字符串结束符'\0'的时候,'\0'被赋予*cp,这同时也是上述赋值表达式的值,这时候表达式的值为假,循环结束。
*******************************************************************************/
char
* __cdecl
strcat
(
char
* dst,
const
char
* src
)
{
char
* cp = dst;
while
( *cp )
cp++;
/* find end of dst */
while
( *cp++ = *src++ ) ;
/* Copy src to end of dst */
return
( dst );
/* return dst */
}
在vs2008中char str1[5]="ab"; char str2[]="hahah"; strcat(str1,str2); cout<<str1<<" "<<strlen(str1);结果为 abhahah 7说明str1是作为指针处理的,没有给出出错提示。
strcpy源码
123456789101112131415/***
*char *strcpy(dst, src) - copy one string over another,
*后面的字符串将覆盖前面的
*
*******************************************************************************/
char
* __cdecl
strcpy
(
char
* dst,
const
char
* src)
{
char
* cp = dst;
while
( *cp++ = *src++ )
;
/* Copy src over dst */
return
( dst );
}
在vs2008中
char str1[5]="ab"; char str2[]="hahahaha"; strcpy(str1,str2); cout<<str1<<" "<<strlen(str1);
结果为hahahaha 8
说明str1是作为指针的,没有给出出错提示。
·当src到达 '\0’时,*cp被赋值为'\0’,整个表达式的值即为'\0’,对应的ASC码值为0 =>while退出
strcmp源码
12345678910111213141516171819202122/***
*strcmp - compare two strings, returning less than, equal to, or greater than
*Exit:
* returns -1 if src < dst
* returns 0 if src == dst
* returns +1 if src > dst
*******************************************************************************/
int
__cdecl
strcmp
(
const
char
* src,
const
char
* dst
){
int
ret = 0 ;
while
( ! (ret = *(unsigned
char
*)src - *(unsigned
char
*)dst) && *dst)
//直到src和dst当前数值不相等或dst为\0时退出while
++src, ++dst;
if
( ret < 0 )
ret = -1 ;
else
if
( ret > 0 )
ret = 1 ;
return
( ret );
}
strncmp源码int strncmp ( char * s1, char * s2, size_t n) 用法:#include <string.h> 功能: 比较字符串s1和s2的前n个字符. 返回结果:如果前n字节完全相等,返回值就=0;在前n字节比较过程中,如果出现s1[n]与s2[n]不等,则返回(s1[n]-s2[n]) 源码实现: int strncmp ( char * s1, char * s2, size_t n) { if ( !n )//n为无符号整形变量;如果n为0,则返回0 return(0); //在接下来的while函数中 //第一个循环条件:--n,如果比较到前n个字符则退出循环 //第二个循环条件:*s1,如果s1指向的字符串末尾退出循环 //第二个循环条件:*s1 == *s2,如果两字符比较不等则退出循环 while (--n && *s1 && *s1 == *s2) { s1++;//S1指针自加1,指向下一个字符 s2++;//S2指针自加1,指向下一个字符 } return( *s1 - *s2 );//返回比较结果 }
strstr源码
extern char *strstr(char *s1, char *s2)
用法:#include <string.h> 功能: 找出s2字符串在s1字符串中第一次出现的位置(不包括s2的串结束符) 返回结果:返回该位置的指针,如找不到,返回空指针。 源码实现:char *strstr( const char *s1, const char *s2 ) { int len2;
len2= strlen(s2);
if(len2 ==0)
return (char *)s1;
for ( ; *s1; ++s1 ) { if ( *s1 == *s2 && strncmp( s1, s2, len2 )==0 ) //这里多加一个判断*s1 == *s2 return (char *)s1; } return NULL; }
itoa源码char* _itoa(int value, char* string, int radix){char tmp[33];char* tp = tmp;int i;unsigned v;int sign;char* sp;if (radix > 36 || radix <= 1)return 0;sign = (radix == 10 && value < 0);if (sign)v = -value;elsev = (unsigned)value;while (v || tp == tmp) //转化操作{i = v % radix;v = v / radix;if (i < 10)*tp++ = i+'0';else*tp++ = i + 'a' - 10;}if (string == 0)string = (char*)malloc((tp-tmp)+sign+1);sp = string;if (sign)*sp++ = '-';while (tp > tmp)*sp++ = *--tp;*sp = 0;return string;}
atoi源码link:剑指offer p250long long core(char *str,bool minus);int _atoi(char *str){long long num=0;long long sum=0;if(str!=NULL &&str!='\0'){bool minus = false;if(*str=='+')str++;else if(*str=='-'){minus=true;str++;}sum=core(str,minus);}return (int)sum;}long long core(char *str,bool minus){long long num=0;while(*str!='\0'){if(*str >='0' && *str <='9'){num=num*10+(*str-'0');if((!minus && num>0x7fffffff )|| (minus &&(0-num)<(signed int)0x80000000)){num=0;break;}str++;}else{num=0;break;}}return num;}