標籤:
strncpy
的用法:它與strcpy
的不同之處就在於複製n
個字元,而不是把所有字元拷貝(包括結尾‘\0‘
)。
函數原型:char * strncpy(char *dst,const char * src, int n)
當src
的長度小於n
時,dst
內的未複製空間用‘\0‘
填充。否則,複製n
個字元到dst
,沒有加‘\0‘
。這裡就要注意在字串dst
結尾處理加‘\0‘
的情況了
strcpy
,strncpy
,strlcpy
的用法好多人已經知道利用strncpy
替代strcpy
來防止緩衝區越界。但是如果還要考慮運行效率的話,也許strlcpy
是一個更好的方式。
strcpy
我們知道,strcpy
是依據 \0
作為結束判斷的,會自動在緩衝區的string
後加\0
,如果 to
的空間不夠,則會引起 buffer overflow
。strcpy
常規的實現代碼如下(來自 OpenBSD 3.9
):
char *strcpy(char *to, const char *from){ char *save = to; for (; (*to = *from) != ‘\0‘; ++from, ++to); return(save);}
但通常,我們的 from
都來源於使用者的輸入,很可能是非常大的一個字串,因此 strcpy
不夠安全。
strcyp_s
它和strcpy()
函數的功能應該一樣的。strcpy
函數,就象gets
函數一樣,它沒有方法來保證有效緩衝區尺寸,所以它只能假定緩衝足夠大來容納要拷貝的字串。在程式運行時,這將導致不可預料的行為。用strcpy_s
就可以避免這些不可預料的行為。
這個函數用兩個參數、三個參數都可以,只要可以保證緩衝區大小。
三個參數時:
errno_t strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource);
兩個參數時:
errno_t strcpy_s(char (&strDestination)[size], const char *strSource ); // C++ only
需要注意的是如果需要使用兩個參數的版本,則strDestination
所指向的空間必須時靜態分配的,而不能是動態new
出出來的堆記憶體。
strncpy
在 ANSI C
中,strcpy
的安全版本是 strncpy
。
char *strncpy(char *s1, const char *s2, size_t n);
但 strncpy
其行為是很詭異的(不符合我們的通常習慣)。標準規定 n
並不是 sizeof(s1)
,而是要複製的 char
的個數。一個最常見的問題,就是 strncpy
並不幫你保證 \0
結束。
char buf[8];strncpy( buf, "abcdefgh", 8 );
看這個程式,buf
將會被 "abcdefgh"
填滿,但卻沒有 \0
結束符了。
另外,如果 s2
的內容比較少,而 n
又比較大的話,strncpy
將會把之間的空間都用 \0
填充。這又出現了一個效率上的問題,如下:
char buf[80];strncpy( buf, "abcdefgh", 79 );
上面的 strncpy
會填寫 79 個 char,而不僅僅是 "abcdefgh"
本身。
strncpy
的標準用法為:(手工寫上 \0
)
strncpy(path, src, sizeof(path) - 1);path[sizeof(path) - 1] = ‘\0‘;len = strlen(path);
strlcpy
複製src
到大小為size
目的緩衝區,最多複製siz-1
個,第size
個位置會被添加‘\0‘
,執行結束後會返回strlen(src)
。所以,如果retval >= siz
,那麼由於目的緩衝區太小src
被截斷了.
size_t strlcpy(char *dst, const char *src, size_t siz);
使用 strlcpy
,就不需要我們去手動負責 \0
了,僅需要把 sizeof(dst)
告之 strlcpy
即可:
strlcpy(path, src, sizeof(path));len = strlen(path);if ( len >= sizeof(path) ) printf("src is truncated.");
並且 strlcpy
傳回的是 strlen(str)
,因此我們也很方便的可以判斷資料是否被截斷,但同時也給程式埋了一個雷,所以,strlcpy
並不屬於 ANSI C
,至今也還不是標準。
C++ 中 strcpy、strcpy_s、strncpy、strlcpy的異同