字符串在C語言中實際是字符數組,由於C比其餘大多數語言更底層,他並無提供字符串這個數據類型,而是採用類似的東西代替,這就是以字符爲元素的數組。數組
char *s="PPYY";ide
上面這個字符串(咱們也把它稱爲字符串字面值),C會把它做爲數組進行操做,函數
char s[]={'P','P','Y','Y'};指針
因此採用s[0],s[1]訪問這個字符串是被容許的,可是須要很是清醒的是,字符串字面值是不能被修改的,由於字符串字面值和字符數組在內存當中的工做方式是不一致的。內存
咱們以Linux系統爲例,粗略說說爲何他們的工做方式不一致,下圖是簡略的內存結構圖:字符串
局部變量區域 |
棧 |
無序組合 |
堆 |
全局區 |
|
只讀存儲區 |
常量區 |
代碼區 |
/*字符串字面值的工做工做方式*/
it
一、字符串字面值 "PPYY"先是存放在常量區,存放的樣子以下:編譯
P |
P |
Y |
Y |
\0 |
(尾部有個\0 ,是字符串的在內存中的結束符,由於C語言並不知道字符串何時結束。)table
二、而後在棧上建立s這個指針變量,用以存放指向常量區"PPYY"字面值的地址。class
這就解釋了爲何咱們嘗試修改字符串字面值的時候,程序會報錯,由於字符串字面值是存放在常量區的。
/*字符數組的工做方式*/
一、"PPYY"這個字符串字面值仍然先是存放在常量區。
二、在棧上建立一個字符數組,數組的長度和數組元素都和先前的字符數組一致。
這個時候咱們在程序中操做這個字符數組的時候,實際上是操做的這個字符串字面值在棧空間中的字符數組副本。
這裏咱們順着這個思路理清楚 char *s這個指針變量和char s[]這個數組變量的不一樣之處在什麼地方。
char *s這個s是存放的常量區"PPYY"字面值的地址;而char s[]這個s表示棧空間中數組第一個元素的內存地址。上面兩個描述,一個是存放,一個表示,由於char *s在初始化的時候,是在內存中分配了char類型的地址變量空間的。而char s[]在初始化的時候,是沒有分配內存空間的,只是程序在編譯的時候,會把這個s替換成數組第一個元素的內存地址。
char s[]和char *s在做爲函數形參時效果是同樣的,即void func_name(char s[])和void func_name(char *s)是等價的,可是此時的數組變量會退化成指針變量,做爲數組變量,咱們能夠經過sizeof()運算符判斷數組的長度,可是指針變量咱們只能獲得這個指針變量自己的長度。