寫項目的時候又被最基礎的 char* , char[] , strncat , strcpy卡了一會,太久沒碰老是搞混,索性在這裏做個筆記:
char* ,const char*,const char* const
const char* str1 = "abc";
// char* str1="abc";
// 有些編譯器允許上面這樣子寫
const char* const str3 = "abc";
// str3 = "def"; 錯誤!!!str3指針不可改變指向!!
printf_s("st1:%p str3:%p\n", str1, str3);
// st1:012E8B30 str3:012E8B30
const char* str1 = "abc";
在這句裏,“abc”,做了3件事:
- 申請了內存(全局變量區)
- 在字符串尾部添加了’/0’(sizeof(“abc”)因此是4,strlen(“abc”)是3,strlen不統計’/0’)
- 返回了字符串的地址,返回類型是const char*,這裏賦值給了str1
所以,const char* str1=“abc” 這句話是正確的(編譯器不同,有時需加上const關鍵字,因爲數組名退化爲的是常量指針)。
如果想限定str1指向,const char* const str3 = “abc” 這樣寫。
而正因爲“abc”申請區域是常量存儲區,很清楚看到printf_s(“st1:%p str3:%p\n”, str1, str3);的地址是一樣的。
分配區域是常量存儲區!!!
char*,char[]
const char* str1 = "abcdef";
cout << strlen(str1)<<endl; // 6
cout << sizeof(str1) << endl; // 4
char str2[7] = "abcdef";
cout << strlen(str2)<<endl; // 6
cout << sizeof(str2) << endl; // 7
printf_s("st1:%p str2:%p\n", str1, str2);
// st1:00F48BD0 str2:00BEFA3C
主要注意的就是,“abcdef”是一個常量,
char str2[10] = "abcdef";
“abcdef”先會在常量存儲區存下來,然後會因爲要賦值給str2,會在棧中開闢一段內存,內存大小爲7個節點(char數組後會自動加一個’\0’),然後又有一個"abc"被保存在棧中。
因此str1和str2地址是不一樣的。
strncat(),strcpy()
strncat()主要功能是在字符串的結尾追加n個字符。
strcpy是一種C的標準庫函數,strcpy把**含有’\0’*的字符串複製到另一個地址空間,返回值的類型爲char。
結合以上:char*,char[]的特性:
char *str1="abcd";
// const char*str1="abcd; 等價
char str2[20] = "1234";
strncat(str1, str2, 4);
像是某些版本VS或者DEV這樣子是不會報錯,但是是不可行的:首先,str1指向的"abcd"的地址是在常量存儲區的,在棧存儲的僅僅是指向該區的地址,是無法對str1指向的常量區("abcd"的地址)進行修改。
char *str1="abcd";
char str2[] = "1234";
strncat(str2, str1, 4);
printf("%s\n", str2);
這樣子反過來就可以了。
strcpy()同理。