strcpy函數怎么用?
首先,使用步驟如下
1.頭文件:#includeltstring.hgt和#includelstdio.hgt。
2.功能:將從src地址開始并包含空終止符的字符串復制到從dest開始的地址空間。
3.描述:src和dest指示的內存區域不能重疊,dest必須有足夠的空間來容納src字符串。返回一個指向目標的指針。
第二,拓展
//C語言標準庫函數strcpy的典型工業最簡單實現。
//返回值:目標字符串的地址。
//參數:des是目標字符串,source是原始字符串。
char*strcpy(char*des,constchar*source){
char*rdes
斷言((des!NULL)ampamp(來源!NULL))
while((*r*source)!#390#39)
返回des
}
//while((*des*source))的解釋:賦值表達式返回左操作數,所以在賦值#390#39之后,循環停止。
例如:
chara[10],b[]{#34COPY#34}
//定義字符數組a,b
strcpy(a,b)
//將副本從B復制到a。
Strcpy函數中的緩沖區溢出及其防范
C語言和C語言以其輕松靈活的風格和寬松的語法限制,受到各類程序員的歡迎。它們是比較常見的編程語言,也是各大高校計算機專業的基礎語言課程。Strcpy函數由于不檢查數組邊界,非常容易造成各種緩沖區溢出漏洞。這些漏洞很容易被利用,導致嚴重的系統問題。使用strcpy函數時要小心。Strcpy函數中的緩沖區溢出及其預防措施將在下面討論。[1]
緩沖區溢出問題
緩沖區溢出是指程序在動態分配的緩沖區中寫入了過多的數據,使得分配的區域溢出。一旦一個緩沖區可以通過使用程序把運行指令放到root權限的內存中,并運行這些指令,就可以用root權限控制計算機了。[1]
Strcpy函數的安全編碼
編程時,通過增加錯誤檢查,可以及時發現錯誤,處理出現的異常。寫strcpy函數時,先把目的緩沖區的長度做得盡可能長,然后檢查目的緩沖區和源緩沖區。如果目標緩沖區或源緩沖區為空,程序將在異常處理中結束。如果源字符串不長于目標緩沖區長度。龍,也要在異常處理中結束程序,以防止溢出。任何程序都很難說是絕對安全的,strcpy函數只能以最安全的處理。只要輸入字符串不以空字符結尾,該函數將隨時終止。這種檢測很容易實現。然而,這種檢測并不能確保該功能一定是安全的。[1]
另外,每增加一個錯誤檢查,都會讓程序更加復雜,可能會產生很多bug,增加很多工作量。最重要的是,即使程序設計得非常仔細,也可能會忽略一些細節,導致不可挽回的錯誤。所以寫程序的時候,最保險的辦法就是盡量不要用strcpy函數。可以在程序開頭添加#definestrcpyUnsafe_strcpy。這樣strcpy函數在編譯時就會產生錯誤,這樣我們在編程時就可以完全拋棄strcpy函數了。當strcpy函數被完全拋棄后,很多依附于strcpy函數的bug也被拋棄。[1]
特殊情況描述
已知strcpy函數的原型是:
char*strcpy(char*strDest,constchar*strSrc)
1.不調用庫函數實現strcpy函數。
2.解釋為什么要返回char*。
不調用庫函數如何實現strcpy函數
strcpy的實現代碼
char*strcpy(char*strDest,constchar*strSrc){
if((NULLstrDest)||(nullstrrc))
//[1]
拋出#34無效參數#34
//[2]
char*strDestCopystrDest
//[3]
while((*strDest*strSrc)!#390#39)
//[4]
返回strDestCopy
}
錯誤做法[1]:
(a)不檢查指針的有效性意味著回答者不注意代碼的健壯性。
使用((!strDest)||(!StrSrc))或(!(strDestampampstrSrc)),說明回答者對C語言中類型的隱式轉換沒有深刻的理解。在這種情況下,從char*到bool的轉換是隱式類型轉換。這個功能雖然靈活,但是會導致出錯概率更大,維護成本更高。所以C特別添加了bool,true和false關鍵字,提供了一個更安全的條件表達式。
(c)當檢查指針的有效性時,使使用((strdest0)||(strrc0))說明回答者不知道使用常數的好處。直接使用文字常量(比如本例中的0)會降低程序的可維護性。雖然0很簡單,但是程序中可能會有很多對指針的檢查。萬一出現筆誤,編譯器可以t找不到,生成的程序包含邏輯錯誤,很難消除。用NULL代替0,如果有拼寫錯誤,編譯器會檢查出來。
錯誤的[2]:
(A)返回新字符串(#34無效參數#34);說明回答者對返回值的用途沒有概念,對內存泄漏沒有警覺。從函數中返回分配在函數體中的內存是非常危險的。他把釋放記憶的義務扔給了毫無戒心的呼叫者。在大多數情況下,調用者不會釋放內存,從而導致內存泄漏。
(B)返回0;,說明回答者沒有掌握異常機制。調用者可能忘記檢查返回值,調用者可能無法檢查返回值(見下面的鏈式表達式)。如果想讓返回值肩負起返回正確值和異常值的雙重功能,結果往往是兩個功能都無效。返回值應該用拋出異常來代替,這樣可以減輕調用者的負擔,使錯誤不被忽略,增強程序的可維護性。
錯誤的[3]:
(一)忘記保存原始strDest值,說明回答者邏輯思維不嚴謹。
錯誤的[4]:
(a)將循環寫成while(*strtestcopy*strsrc);,同[1](B)。
(b)循環被寫成while(*strRC!#390#39)*strdest*strsrc;,表明被告對邊界條件的檢查是薄弱的。在循環體結束后,strDest字符串的末尾沒有正確添加#390#39。
解釋為什么要返回char*
返回strDest的初始值使函數能夠支持鏈表達式,這增加了"附加值和利潤的函數。功能相同的功能,如果可用性能得到合理提升,自然更理想。
鏈表達式的形式如下:
intiLengthstrlen(strcpy(strA,strB))
另一個例子是:
char*strAstrcpy(新char[10],strB)
返回strSrc的原始值是錯誤的。第一,源字符串必須是已知的,返回沒有意義。第二,不能支持第二個例子那樣的表達式。第三,為了保護源字符串,形參使用const限制strSrc引用的內容,返回constchar*作為char*。類型不匹配,編譯器報告錯誤。
在上面的語句中,循環語句
while((*strDestCopy*strSrc)!#390#39)
很難理解,這句話可以理解為下面的操作。
第一種:
while(1){
炭化溫度
*strDestCopy*strSrc
溫度*strSrc
strDestCopy
strSrc
如果(#390#39溫度)
破裂
}
第二種類型:
while(*strrc!#390#39){
*strDestCopy*strSrc
strDestCopy
strSrc
}
*strDestCopy*strSrc
即:
while(*strrc!#390#39){
*strDestCopy*strSrc
}
*strDestCopy“0”
使用示例
//例1:將一個字符串復制到一個足夠長的字符數組中。在本例中,字符數組是一個,長度為20。
//缺點:如果數組長度不足以容納整個字符串,程序會崩潰。
#includeltiostreamgt
#includeltstdlib.hgt
使用命名空間標準
char*strcpy(char*strDest,constchar*strSrc){
char*strDestCopystrDest
if((NULLstrDest)||(nullstrrc))拋出#34無效參數#34
while((*strDest*strSrc)!#390#39)
返回strDestCopy
}
intmain(intargc,char*argv[]){
chara[20],c[]#34我是老師!#34
嘗試{
strcpy(a,c)
}catch(char*strInfo){
coutltltstrInfoltltendl
退出(-1)
}
coutltltaltltendl
返回0
}
//例2:預置了兩個字符指針,一個指向字符串,一個指向NULL,在程序運行過程中復制。
#includeltiostreamgt
使用命名空間標準
char*strcpy(char*strDes,constchar*strSrc)
//函數聲明
intmain(){
constchar*strrc#34helloworld#34
char*strDesNULL
strDesstrcpy(strDes,strSrc)
coutltlt#34strsrc#34ltlstrsrcltltendl
coultlt#34strdes#34ltltstrdestltendl
如果(strDes!NULL){
免費(strDes)
strDesNULL
}
返回0
}
char*strcpy(char*strDes,constchar*strSrc){
斷言(strSrc!空)
//如果strSrc為NULL,則引發異常。
strDes(char*)malloc(strlen(strsrc)1)
//多一個空間用于存儲字符串終止符#390#39。
char*pstrDes
while(*strrc!#390#39){
*p*strSrc
}
*p#390#39
返回strDes
}
還有一個模擬算法:
char*strcpy(char*dest,constchar*src){
char*pdest
while(*src!#390#39){
*dest*src
目標服務中心
}
*目的地#390#39
返回p
}
與strncpy的區別
第一種情況:
你好嗎?#34
charname[20]#34abcdefghijklmnopqrs#34
strcpy(名稱,p)
//名字改成#34你好嗎?#34gt正確!
strncpy(name,p,sizeof(name))
//名字改成#34你好嗎?#34gt正確!后續字符將為空。
第二種情況:
你好嗎?#34
字符名稱[10]
strcpy(名稱,p)
//目標字符串的長度小于源字符串的長度,錯誤!
名稱[sizeof(name)-1]
//而上一步,彌補了結果,但這是不可取的。因為上一步的錯誤處理方法是不確定的。
strncpy(nam
keil報錯invalidargument?
Keil報告了invalud參數,這意味著非法參數,并且不支持當前語法。