C常用函数t的实现

来源:互联网 发布:威廉马歇尔 知乎 编辑:程序博客网 时间:2024/05/29 14:42

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;

}

}



 

原创粉丝点击