strcat是將一個字符串鏈接到另外一個字符串上的函數,具體形式如下:
char* strcat(char* dest,const char* src)
函數的具體流程如下:
1.先查找dest字符串的結尾(即'\0')
2.然后從dest字符串的結尾位置(即'\0'所在的位置)開始,復制src中的字符(包括結尾'\0')。產生的結果是dest的結尾'\0'會被覆蓋掉,最后產生一個新的結尾。
3.將dest返回(一般用不到)
注意事項
1.dest必須被初始化,即包含一個'\0'結尾。用malloc分配字符串時,經常發生沒有初始化的錯誤。有時候也會正常執行,是因為分配到的內存中,第一個單元的內容剛好為'\0'。但是不能保證每次都這么好運。所以初始化還是有必要的。
可以這樣進行初始化
char* str=(char*) malloc(sizeof(100));
*str='\0';//注意這里是單引號,以為*str表示str所在地址存儲的一個char
或者
*str=0;
也可以這樣strcpy(str,"");
2.src也必須初始化,包含一個'\0'的結尾,不過這個一般發生錯誤的概率較小,因為很多時候直接使用一個字符串做參數strcat(dest,"hello world.")。
3.dest所指向內存的大小必須
>=strlen(dest)+strlen(src)+1,否則會發生
不可知的錯誤,比如
亂碼。使用之前要先確認dest的空間足夠大再使用strcat函數。
glibc中的源碼 strcat.c
char *
strcat (dest, src)
char *dest;
const char *src;
{
char *s1 = dest;
const char *s2 = src;
reg_char c;
/* Find the end of the string. */
do
c = *s1++;
while (c != '\0');
/* Make S1 point before the next character, so we can increment
it while memory is read (wins on pipelined cpus). */
s1 -= 2;
do
{
c = *s2++;
*++s1 = c;
}
while (c != '\0');
return dest;
}
strcpy是將一個字符串復制到另外一個字符串地址上的函數,函數形式如下:
char* strcpy(char* dest,char* src)
函數流程
1.將src中的字符(包括結尾'\0')一個個復制到dest中,dest原來的字符將被覆蓋掉。
2.將dest指針返回
注意事項:
1.dest可以不初始化,比如
char *str=(char*) malloc(sizeof(char)*100);
strcat(str,"hellow world!");
2.利用這一特性,可以用來初始化字符串變量
strcat(str,"");將達到和
*str=0;一樣的效果
glibc中strcpy.c的函數實現
char *
strcpy (dest, src)
char *dest;
const char *src;
{
reg_char c;
char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);
const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
size_t n;
do
{
c = *s++;
s[off] = c;
}
while (c != '\0');
n = s - src;
(void) CHECK_BOUNDS_HIGH (src + n);
(void) CHECK_BOUNDS_HIGH (dest + n);
return dest;
}
有沒有發現這個代碼實現的很tricky,off是(dest的地址-src的地址-1)
c = *s++;
s[off] = c;
相當於
c = *s++;
dest++= c;
不過我感覺這樣的代碼格式不值得推薦,效率上一樣,但是閱讀性更差。讓人很難看懂。下面就扯兩句,代碼寫的讓人看得懂,比少些幾行,提高一點點效率更重要。更何況,很多時候經過編譯器的優化,少些的那幾行不見得更高效。具體的可以看看《重構 改善既有代碼的設計》這本書。先聲明一下,我不是賣書的,和這本書的作者沒有一毛錢關系:-D。
本文由ladd原創,歡迎轉載,但請注明出處: