其實這個問題已經遇到很多次了,每次都百度,當時都明白了,過一會就忘記了
現在暫時記錄整理一下,有時間作總結
首先,C語言沒有字符串變量,只有字符串常量,所以字符串變量的任務就交給字符數組解決了!
字符串常量:"qwer"
嗯,這是一個字符串常量,字符串常量會在結尾加一個結束符'\0',所以這個字符串常量的實際長度為5
字符數組:char[5];
重點來了,這里經常容易錯誤
1.首先,這個字符串數組的長度為5,這一定沒問題:從c[0]到c[4]。
2.然后,這其中字符數組必須也有一個結束符號'\0',它在最后一個有意義的字符之后的一個位置(如果有意義的字符是2個的話,結束字符就在a[2]上,如果有意義的字符是3個的話,結束字符就在a[3]上)
嗯,到這里,是不是覺得結束字符開始麻煩了,感覺設計C語言的人是不是多此一舉呢,Naive!看看下面你就知道為什么要有這個討人嫌的結束字符了,都是因為 有字符串常量啊,我們想要字符數組達到字符串變量的效果,就必須要這個字符
char c[5]={"qw"};
std::cout<<c;
這兩行代碼的的輸入結果是"qw",有人會想,這個c不是數組名,也就是地址嗎?如果這里不明白,建議補補基礎知識,這里的c不是地址,是數組名,沒有發生自動類型轉 換,它能夠代表數組,好,那么輸出的是字符串數組了,按照道理來說,這個字符串數組是五個長度啊,要輸出可是應輸出五個來着,后面三個是莫名其妙的東西,這個就 要看字符串數組默認初始化了,可是不管怎樣初始化,都要輸出五個,這可怎么辦?也許輸出的是燙燙燙燙燙呢?這個時候,就該結束字符'\0'起作用了,有了結束字符, 我們就可以直接通過數組名輸出所有的字符,不產生任何副作用,這個時候的字符數組名,完全可以當作變量名玩啊
好了,這么長的一段小字是我的意淫,我猜C語言的設計者應該是這樣想的,怎樣想到的呢?對比C++,好,不扯了
3.理解了為什么要有結束字符,接下來就是一些栗子了
1.char[5]={'q','w','e','r'}(正確寫法,末尾自動添加結束符)
2.char[5]={'q','w','e','r'.'t'};(錯誤寫法,編譯器不會報錯,輸出字符串數組名的時候結尾會有燙燙燙)
3.char[]={'q','w','e','r'};(錯誤寫法,編譯器不會報錯,輸出字符串數組名的時候結尾會有燙燙燙,因為並不知道字符串的長度,無法推斷出結束符的位置,可以理解為編譯器不那么智能)
4.char[]={'q','w','e','r','\0'};(正確寫法,編譯器可以推斷出字符串結束符號的位置)
5.char[5]="qwer";(正確寫法,末尾自動添加0)
6.char[5]={"qwer"}(正確寫法,末尾自動添加0)
7.char[5]="qwert"(正確寫法,末尾自動添加0)
8.char[5]={"qwert"}(錯誤寫法,編譯器會報錯)
9.char[]="qwer"(正確寫法,結尾自動添零,推斷出字符串長度)
10.char[]={"qwer"}(正確寫法,結尾自動添零,推斷出字符串長度)
11.char[5];
a[0]='q'
a[1]='w'
a[2]='e'
a[3]='r'
(錯誤寫法,編譯器不會報錯,輸出字符串數組名的時候結尾會有燙燙燙)
總結:經過以上分析可以看到
1雙引號的字符串常量寫法是最好的
1.除非算上結束符號之后超過了數組長度,否則都是對的
2.雙引號字符串常量的寫法會自動添加結束符號,所以不要畫蛇添足,自己加結束符號,否則會超過長度)
2.單引號的寫法除了c[5]={‘q’,‘w’,‘e’}則這種既確定了長度,又留有足夠空間可以添加結束符號,並且還是采用的初始化列表初始化的,滿足這三個條件才才會自動添加0,除此之外不手動加0的全部是錯的!
3.strlen()函數求得是不帶'/0'結束符號的字母長度,如果沒有遇到結束符號,那么求出的長度肯定大於得到的長度
4.關於字符數組,字符串常量和“指向字符串的指針”
char p1[]="abcde";
char *p2=“abcde”
p1是字符數組,"abcde"是字符串常量
p2是"指向字符串的指針"
char p1[5]; p1="abcde";//這種寫法是錯誤的!,因為數組類型的數據必須初始化,並且不允許直接賦值
char *p2;p2="abcde";//這種寫法是對的(全局變量,內置類型:包括基本和復合),因為是個指針變量 ,而不是數組,p2可直接訪問文字常量區
char c='c';
另外 char*p3=&c也是可行的