strcpy, memcpy, memmove, memset的实现
strcpy() 字符串拷贝
C代码
char *strcpy(char *strDest, const char*strSrc)
{
assert((strDest!=NULL) && (strSrc !=NULL));
char *address = strDest;
while( (*strDest++ = * strSrc++) != '\0');
returnaddress ;
}
memcpy 拷贝不重叠的内存块
C代码
void *memcpy(void* pvTo, void* pvFrom,size_t size) //byte是java里的变量类型
{
assert(pvTo != NULL && pvFrom != NULL);
byte* pbTo = (byte*)pvTo;
byte* pbFrom = (byte*)pvFrom;
/* 内存块重叠吗?如果重叠,就使用memmove */
assert(pbTo>=pbFrom+size || pbFrom>=pbTo+size);
while(size-->0)
*pbTo++ == *pbFrom++;
return pvTo;
}
memmove 可拷贝重叠的内存块
C代码
void* memmove(void *dest, const void*src,size_t n)
{
if (n == 0) return 0;
if (dest == NULL) return 0;
if (src == NULL) return 0;
char *psrc = (char*)src;
char *pdest = (char*)dest;
if((dest <= psrc) || (pdest >= psrc + n)) /*检查是否有重叠问题*/
{
for(int i=0; i < n; i++) /*正向拷贝*/
{
*pdest = *psrc;
psrc++;
pdest++;
}
}
else /*反向拷贝*/
{
psrc += n;
pdest += n;
for(int i=0;i<n;i++)
{
psrc--;
pdest--;
*pdest = *psrc;
}
}
return dest;
}
memset 把buffer所指内存区域的前count个字节设置成字符cvoid* memset(void* buffer, int c, int count)
C代码
{
char* pvTo=(char*)buffer;
assert(buffer != NULL);
while(count-->0)
*pvTo++=(char)c;
return buffer;
}
1 首先,数组名不能当作赋值对象,比如下面的代码:
C代码
char *s="abc";
char *s1="bcd";
s1=s;
printf("%c\n",s1[0]);
可以正常运行,如果把这边的指针变为数组就会出错。
2 下面阐述一下,指针和数组各自是如何访问的:
C代码
char s[]="abc"; c=s[i];
编译器符号表有一个符号 s 地址为 1234,然后首先取i的值,把i和1234相加,然后取出(i+1234)的内容付给c.
C代码
char *s="abc"; c=s[i];
编译器符号表有一个符号s,他的地址为1234,然后取地址1234的内容,就是'5678',然后把i和5678相加,然后取出(i+5678)的内容付给c.
大家可以看下下面的这个程序:
C代码
#include <stdio.h>
void main()
{
char *s="abc";
char s2[]="789";
printf("%d\n",&s);
printf("%d\n",&s[0]);
printf("%d\n",&s2);
printf("%d\n",&s2[0]);
}
呵呵,s和s[0] 的地址竟然不一样。
3 定义指针时编译器并不为指针所指向的内容分配空间,它只分配指针本身的空间,除非在声明的同时付给指针一个字符串常量初始化。比如:
C代码
char *s="abc";
可是只有对字符串常量才是如此,其他的类型都会出错。
4 数组和指针的相同点。
。表达式中的数组名(不同于声明)被编译器当做一个指向数组第一个元素的指针。
。下标总是和指针偏移量相同,a[i]总是被编译器改写成*(a+i)这种形式来访问。(比如:a[6]和6[a]是一样的)
。在函数参数的声明中,数组名被编译器当做一个指向数组第一个元素的指针
可以看下下面的代码的输出。
C代码
#include <stdio.h>
void f(char s[]);
void g(char *s);
char s2[4]="789";
void main()
{
printf("%d\n",&s2);
printf("%d\n",&(s2[0]));
f(s2);
g(s2);
}
void f(char s[4])
{
printf("%d\n",&s);
printf("%d\n",&(s[0]));
}
void g(char *s)
{
printf("%d\n",&s);
printf("%d\n",&s[0]);
}
为什么c要做成这种呢,其实很简单,就是在c中调用函数的时候会把实参进行拷贝,而如果实参是数组的话,拷贝的开销太大,所以不如指针方便.
char *stristr(char *str1, char *str2)
{
char *str0 = null;
slen1 = strlen(str1);
slen2 = strlen(str2);
for( ; slen1 > slen2; str1++, slen1--)
{
while(*str1 != *str2)
{
str1++;
slen2--;
if(slen2 != slen1)
{
return null;
}
}
str0 = str1;
while(*str0 == *str2)
{
str0++;
str2++;
if(*str2 == '\0')
return str1;
}
}
}