char *指向的內容不可修改

c語言不夠紮實,學c++和linux時會遇到一些奇怪的問題。

在學信號時,演示代碼

char *str = "resource";

str = 'H';

報了段錯誤。一下子不能理解,爲啥str指向的內容不可修改。

在網上查了一下資料,有了答案。

(斜體爲網上內容,來源:http://bbs.chinaunix.net/viewthread.php?tid=1084610&page=1#pid8256820):

"resource"是字符串常量。

對於 char *str = "resource";

把"resource"的值----也就是字符串常量字面值,也就是"resource"的地址,準確來說是起始地址----賦給字符指針 str,Linux下,"resource"字符串常量是存放於只讀數據區的,一般來說,32位機器上,在Linux中,堆,全局數據,常量等都是存放於從0x8048000開始的內存地址,向上增長。可以打印一下"resource"的地址來進行驗證。char *str = "resource",就是把"resource"的首地址賦給str,所以str 存放的是一個只讀數據區的地址,對只讀區的數據進行寫操作是禁止,具體由相應的操作系統進行判斷以及處理。


而對於 char str[] = "resource";

str[]是一個字符數組,編譯器首先在棧中分配一定的連續空間用於存放“resource”中的字符以及結尾符,然後把字符串常量的內容,也就是
"resource"中的各個字符和結尾符複製到這個棧中的連續空間中。str是數組名,用來表示這個連續棧空間的起始地址,所以str中存放的是棧地址,這個地址的數據是可寫的。一般來說,32位機器上,在Linux中,棧地址空間從3G(0xbfffffff)開始向下增長。

可以用語句printf("%x\n", str)來打印出str中存放的地址,來驗證一下這個地址屬於棧還是屬於只讀數據區。


以下有兩種寫法是沒有問題的:

char* str = new char[12];

strcpy(str, "resource");

str[6] = k; //沒問題

*(str+6) = 'k'; //沒問題


char str[] = "resource";

str[6] = 'k';

*(str+6) = 'k';

但是要注意,下面的代碼也是不行的

char* p =newchar[12];
p
="resource";
p[
6]='k';//報錯

在編譯器調試狀態下,可以很容易地看到,剛分配完內存的p的地址與給p賦值後的地址明顯不同,所以經過後一個賦值語句後,p又重新指向了只讀內存區,所以又不能修改了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章