久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

strcpy的實現(xiàn)與用法總結

 helloworld441 2015-09-22

已知strcpy函數(shù)的原型是:

char *strcpy(char *dst, const char *src);

  1. 實現(xiàn)strcpy函數(shù)
  2. 解釋為什么要返回char *
  3. 假如考慮dst和src內存重疊的情況,,strcpy該怎么實現(xiàn)

1.strcpy的實現(xiàn)代碼

復制代碼
char * strcpy(char *dst,const char *src)   //[1]
{
    assert(dst != NULL && src != NULL);    //[2]

    char *ret = dst;  //[3]

    while ((*dst++=*src++)!='\0'); //[4]

    return ret;
}
復制代碼

[1]const修飾

源字符串參數(shù)用const修飾,防止修改源字符串,。

[2]空指針檢查

(A)不檢查指針的有效性,,說明答題者不注重代碼的健壯性。

(B)檢查指針的有效性時使用assert(!dst && !src);

char *轉換為bool即是類型隱式轉換,,這種功能雖然靈活,,但更多的是導致出錯概率增大和維護成本升高。

(C)檢查指針的有效性時使用assert(dst != 0 && src != 0);

直接使用常量(如本例中的0)會減少程序的可維護性,。而使用NULL代替0,,如果出現(xiàn)拼寫錯誤,編譯器就會檢查出來,。

[3]返回目標地址

(A)忘記保存原始的strdst值,。

[4]'\0'

(A)循環(huán)寫成while (*dst++=*src++);明顯是錯誤的。

(B)循環(huán)寫成while (*src!='\0') *dst++=*src++;

循環(huán)體結束后,,dst字符串的末尾沒有正確地加上'\0',。

2.為什么要返回char *?

返回dst的原始值使函數(shù)能夠支持鏈式表達式,。

鏈式表達式的形式如:

int l=strlen(strcpy(strA,strB));

又如:

char * strA=strcpy(new char[10],strB);

返回strSrc的原始值是錯誤的,。

其一,源字符串肯定是已知的,,返回它沒有意義,。

其二,不能支持形如第二例的表達式,。

其三,,把const char *作為char *返回,類型不符,,編譯報錯,。

3.假如考慮dst和src內存重疊的情況,strcpy該怎么實現(xiàn)

char s[10]="hello";

strcpy(s, s+1); //應返回ello,,

//strcpy(s+1, s); //應返回hhello,,但實際會報錯,因為dst與src重疊了,,把'\0'覆蓋了

所謂重疊,,就是src未處理的部分已經(jīng)被dst給覆蓋了,只有一種情況:src<=dst<=src+strlen(src)

C函數(shù)memcpy自帶內存重疊檢測功能,,下面給出memcpy的實現(xiàn)my_memcpy,。

復制代碼
char * strcpy(char *dst,const char *src)
{
    assert(dst != NULL && src != NULL);

    char *ret = dst;

    my_memcpy(dst, src, strlen(src)+1);

    return ret;
}
復制代碼

my_memcpy的實現(xiàn)如下

復制代碼
char *my_memcpy(char *dst, const char* src, int cnt)
{
    assert(dst != NULL && src != NULL);

    char *ret = dst; 

    if (dst >= src && dst <= src+cnt-1) //內存重疊,,從高地址開始復制
    {
        dst = dst+cnt-1;
        src = src+cnt-1;
        while (cnt--)
            *dst-- = *src--;
    }
    else    //正常情況,從低地址開始復制
    {
        while (cnt--)
            *dst++ = *src++;
    }
    
    return ret;
}

庫函數(shù)strcpy其實有幾個漏洞
1.傳入的指針沒有非空判斷
代碼:
char a[]="hello";
strcpy(a,NULL);
編譯和運行:編譯通過,,運行段錯誤
[root@fedora7 code]# gcc test.c -o test
[root@fedora7 code]# ./test
Segmentation fault
2.沒有檢查兩個字符串是否以NULL(即'\0')結尾
代碼1:
char b[10]="1234567890"; //注意這里的字符串已經(jīng)越界了
strcpy(b,'a'); //這里的2個字符串都沒有結尾標志
編譯和運行:運行段錯誤
[root@fedora7 code]# gcc test.c -o test
test.c: In function ‘test’:
test.c:61: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast
[root@fedora7 code]# ./test
Segmentation fault
代碼2:
將代碼1中的
strcpy(b,'a');
換成
strcpy(b,"a");
編譯和運行:都沒有問題
[root@fedora7 code]# gcc test.c -o test
[root@fedora7 code]# ./test
a
3.目標字符串長度<源字符串長度 沒有判斷
代碼:
char a[5]="haha";
char b[10]="123456789";
strcpy(a,b);
puts(a);
puts(b);
編譯和運行:運行段錯誤
[root@fedora7 code]# gcc test.c -o test
[root@fedora7 code]# ./test
123456789
123456789
Segmentation fault
(這個段錯誤不太好解釋,,沒想明白)

4.代碼實例:
//date:20100820
//function:my_strcpy
//note:模仿strcpy
/*
strcpy原型:char *strcpy(char *dstr,const char *sstr);
庫函數(shù)解析:將字符串sstr的字符拷貝到dstr,返回dstr的地址,。(注意返回值)
*/
char * my_strcpy(char *dstr,const char *sstr); //const說明源字符串為只讀變量
test()
{
char a[]="hello";
char b[32];
my_strcpy(b,a);
puts(b);
}
char * my_strcpy(char *dstr,const char *sstr)
{
if(!sstr || !dstr) //防止空指針操作
return NULL;
#if 0 //方法一
printf("Method A\n");
while(*sstr!='\0')
*dstr++=*sstr++;
*dstr='\0'; //注意復制時需要加上字符結束標志
#else //方法二
printf("Method B\n");
while((*dstr++=*sstr++)!='\0'); //這里不需要加上字符結束標志,,想想為什么呢?
#endif
}
main()
{
test();
}

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多