總結:
1.字串常量是不可改變的,放在文字常量區,也就是在靜態儲存區上。
2.除了char buffer[20]= "hello ";和strcpy(p, "hello ");這兩個情況外,程式中出現的字串都應該被視為字串常量了.
如const char *p= "hello ";
簡單地說,除了存在棧和堆上的字串才不是字串常量.其餘的都是字串常量.
舉乙個例子:char buffer[20]= "hello ";這個字串是用來初始化字元陣列buffer的,存在棧上,不是乙個字串常量,可以用下標讀寫其值.又比如,char *p=malloc(...);
strcpy(p, "hello ");這個 "hello "也不是乙個字串常量,因為是在堆上,也可以用指標p進行讀寫.至於在這兩者的前面加上const修飾,雖然表明 "hello "是不允許更改的,但是對於字串來說,不能說明是字串常量.因為,const要修飾的不是明確說hello是不可寫的,而是說p指向的這段記憶體區域是不可寫的.修飾的物件是不同的,只是恰巧這段區域裡存的是hello這個字串(說得有點繞了吧,你再堅持一下).
除了這兩個情況以外,程式中出現的字串都應該被視為字串常量了.
比如const char *p= "hello ";這個字串是存放在靜態儲存區上的,是不可以更改的.它的有效範圍是整個程式的生命期.如果有另外的語句p= "nb ";那麼,hello這個字串將會永遠不被引用,但是它會存在於整個程式的生命期.這才是真正的字串常量.
/如下**:
char a="hello";
a[0]='x';//ok
printf("%s ", a);
char *pl="world";
pl[0]='h';//執行時錯誤
*pl='x';//執行時錯誤
printf("%s ", pl);
char *s=null;
s=(char*)malloc(sizeof(char)*6);//讓俺的s到堆上去
strcpy(s, "hello ");
s[0]='x';//ok
printf("%s ", s);
"hello "是字元常量。但char *s定義的是字元指標的。
s[0]= 'x ';當然是錯誤的,因為s[0]其實說的就是 'h '啦,h是常量來的,當然不能修改,假如你需要修改的話請用。
char s[6]= "hello ";
s[0]= 'x '; 就沒事了。 其實char *pl="world";最好寫成const char *pl="world";;以免被誤用
s不是常量
指向常量
因此在此應用中不能更改
char *s= "ddd ";
一般應該定義成 const char *s = "dddd ";
如果想修改字串字元的值就用char a="hello";
下面的觀點總結得很好。
void main()
char *a = "hello world";
char b = "hello world";
*a = 'c';
b[0] = 'c';
編譯一下,編譯通過,執行一下,崩潰了,這是為什麼呢?
下面我們就來詳細的分析一下:
當我們雙擊執行上述編譯連線之後的.exe的時候,從邏輯上,作業系統是這樣子做的,
char *a = "hello world";首先,作業系統在編譯器規劃記憶體方案中的的文字常量區分配一段記憶體(是連續的嗎?),儲存"hello world"字串(以二進位制的形式),然後在棧區分配乙個記憶體,儲存"hello world"字串所在記憶體的首位址。
char b = "hello world";作業系統在編譯器規劃的記憶體方案中的棧區分配一段連續記憶體空間(12個位元組),儲存"hello world"字串(以二進位制的形式)。
那麼當我們*a = 'c';的時候,就是試圖修改文字常量區的內容,但是文字常量區儲存的可都是常量,常量一經初始化,就不允許被修改,所以產生錯誤,於是杯具就發生了……
而b[0] = 'c';是修改的棧區陣列的內容,當然是合法的啦。
怎麼讓編譯器幫我們檢查出錯誤呢?這就需要我們巧妙的使用const來顯示的告訴編譯器,哥定義的內容是不允許被修改的!
const char *a = "hello world";或者
char const *a = "hello world";
這樣a就變成了乙個常量指標,意思是說a是乙個「指向常量的指標」,那麼a所指向的記憶體區域的內容是不允許被修改的。
既然說到常量指標,我們不得不區分一下指標常量和常量指標這兩個概念。
常量指標:指向常量的指標,是說該指標所指向的記憶體區域的內容是常量,不可以被修改,例如:
char array1 = "hello world";
const char a = array1;
*a = 'c';
這樣子是不可以的,但是我們可以修改該指標所指向的記憶體區域,例如:
char array1 = "hello world";
const char a = array1;
char array2 = "hello china";
a = array2;
這樣子是可以的,因為該指標不是乙個指標常量。
指標常量:該指標是乙個常量,就是說該指標所指向的記憶體是不可以被改變的,但是該指標所指向的記憶體所儲存的內容是可以被改變的,例如:
char array1 = "hello world";
const char a = array1;
char array2 = "hello china";
a = array2;
這樣子是不可以的,因為它試圖為指標a重新賦值。
char array1 = "hello world";
const char a = array1;
*a = 'c';
這樣子是可以的,因為該指標不是乙個常量指標(指向常量的指標)
乙個程式的執行起來後,其在記憶體中有5個區域
1. 程式**區
這個很簡單,**要執行,肯定要載入進記憶體, 我們不必關心。
2. 文字常量區
一般我們這樣定義乙個字串時,其是在文字常量區的:
char* s1 = "hello, world";
char* s2 = "hello, world";
if(s1 == s2)
printf("s1和s2指向同乙個在文字常量區的字串");
這裡, s1和s2指向的是同乙個字串
3. 靜態儲存區
全域性變數,靜態變數會放在這個區域,事實上,全域性變數也是靜態的。
以上1,2,3三個區域的內存在程式起來的時候就開闢好了的。
4. 棧
區域性變數就是在棧裡的。另外,函式呼叫時的引數也是在棧裡的,這個現在不必關心
5. 堆
malloc或new出來的記憶體就是在堆裡的,需要程式設計師自己管理清除。
常量,字串常量
對於普通變數常量 常量摺疊 是 就是在編譯器進行語法分析的時候,將常量表示式計算求值,並用求 得的值來替換表示式,放入常量表。可以算作一種編譯優化 include void main 輸出 3 2 我只是改了這個位址內容,但是e還是2,因為編譯器在優化的過程中,會把碰見的const全部以內容替換掉 ...
字串常量
1.當乙個字串常量出現於表示式中時,它的值是乙個指標常量。編譯器被這些指定字元的乙份拷貝儲存在記憶體的某個位置,並儲存乙個指向第乙個字元的指標。陣列名用於表示式中時,它的值也是指標常量 2.xyz 1 因為字串常量實際上是個常量指標,這個表示式計算 指標值加上1 的數值。它的結果是個指標,指向字串中...
字串常量
來自 常量字串為什麼位於靜態儲存區?char c chenxi 書上說 chenxi 這個字串被當作常量而且被放置在此程式的記憶體靜態區。那一般的int i 1 1也是常量,為什麼1就不被放置在此程式的記憶體靜態區了呢?請高手指點!所有的字元竄常量都被放在靜態記憶體區 因為字串常量很少需要修改,放在...