標籤:style blog http io 使用 ar 檔案 資料 sp
C語言沒有一種顯式的資料類型是字串的。
C語言儲存字串:字串常量(不能修改);字元數組或動態分配的記憶體(可以修改)
****************************************************
9.1 字串基礎
字串概念:字串是以一個位元模式為全0的NUL位元組結尾的0個或多個字元
NUL位元組是終止符,字串的長度不包含NUL位元組
標頭檔string.h包含了使用字串函數所需的原型和聲明(可以在linux中查看,有很多函式宣告)。
****************************************************
9.2 字串長度
size_t是一個不帶正負號的整數類型。定義與stddef.h標頭檔
做算術運算的時候不帶正負號的整數可能導致不可預料的結果(想想,見9.2)
****************************************************
9.3 不受限制的字串函數
——》複製字串 strcpy函數: char *strcpy( char *dst, char const *src);
Note:
1.複製字串也會複製NUL位元組;
2.如果dst目標字元數組空間不足以容納需要複製的字串,strcpy將侵佔數組後面的部分記憶體空間(因為strcpy無法判斷目標字元數組的長度,這也是”不受限制“的含義吧)
——》連接字串 strcat函數: char *strcat( char *dst, char const *src );
Note:
1.這個函數找到dst的末尾(NUL位元組嗎),把src字串的一份拷貝添加到這個位置
2.這個函數也有strcpy的特點,如果dst空間不足以容納需要複製的字串了,則也將侵佔數組後面的部分空間
——》字串比較 strcmp: int strcmp(char const *s1, char const *s2);
Note:
1.這個函數的結果符合“字典比較”
****************************************************
9.4 長度指定了限制的字串函數
上面沒有受限的函數是以尋找字串結尾的NUL位元組來判斷長度;這裡的函數指定進行複製或比較的字元數
——》strncpy函數:char *strncpy( char *dst, char const *src, size_t len );
Note:
1.把源字串src的指定數目字元複製到目標數組dst;如果src沒有len個字元,則會用NUL位元組填充到dst
2.如果是strlen(src)大於len,那麼只有len個字元會進行複製。!但是,它的結果將不會以NUL位元組結尾。(也就是說,strncpy調用的結果可能不是一個字串哦)
——》strncat函數:char *strncat( char *dst, char const *src, size_t len);
Note:
1.strncat在串連完後,會自動在結果後加上一個NUL(因此這還是比較安全的,不會因為沒有NUL而在其他函數中出現問題),例如下程式
#include <string.h>#include <stdio.h>int main(){char *src = "world";char dst[7] = "hello";strncat(dst, src, 5);printf("%s", dst);return 0;}
因為dst容量(7)不夠裝下helloworld(11),因此strncat會侵佔幾個dst後面的位元組,但是在侵佔完後,strncat還是會加上一個NUL位元組。因此既有不安全的一面(侵佔後續位元組)也有安全的一面(自動加NUL位元組)
2.在src的長度不夠len時,它不會用NUL位元組繼續填充dst
*************************以下是一些相關的辨析
#include <string.h>#include <stdio.h>int main(){char *src = "world";printf("length of src is %d\n", sizeof(src));printf("length of src is %d\n", strlen(src));char dst[7] = "hello";int mat[100];strncat(dst, src, 9);printf("%s\n", dst);printf("length of dst is %d\n", sizeof(dst));printf("length of src is %d\n", sizeof(src));printf("length of src is %d\n", strlen(src));printf("length of mat is %d\n", sizeof(mat));return 0;}運行結果為
這說明了幾點:
1.對於數組名來說,一般是作為指標,但是在sizeof(數組名)中,是求取了數組佔用的“位元組”數;
2.在strncat後,輸出helloworld後,對dst數組求位元組數卻還是7. 說明數組長度是被記錄下來的,不會變化了。但是往後只要用%s格式輸出dst,都會輸出helloworld。因為在後面都加入了‘\0‘;
3.完全不解!為什麼在開始strlen(src)還有5,但是在調用了strncat之後strlen(src)就只有1了?求解答~
再看以下的程式
#include <string.h>#include <stdio.h>int main(){//1 *src = "hello";printf("length of src is %d\n", sizeof(src));// 2printf("length of 'hello' is %d\n", sizeof("hello"));// 3char haha[] = "hello";printf("length of haha is %d\n", sizeof(haha));return 0;}
運行結果為
這說明了以下幾點:
1. 行1&2結合,我的分析是,在1中src在可重定位目標檔案中是一個存在於符號表中的標識符,是一個指標變數,以常量字串“hello”的起始地址初始化(運行時);而在2中“hello”是一個常量字串,在運行前已經存放好,放在可重定位目標檔案(編譯彙編之後,連結之前產生的檔案).rodata segment中(?不對耶,用objdump查看了,行1中的“hello”確實存放在rodata段中,但是sizeof(“hello”)中的“hello”沒有放在rodata中,因為若刪去第1行,則rodata中沒有hello了,如是刪去了第1行兩句話)
2.結合2&3分析,說明字元數組包含了‘\0‘
【C】字串,字元和位元組(C與指標第9章)