2010-06-02 23 views
2

1-幾個問題這是如何工作的:關於字符指針

char *ptr = "hi"; 

現在,編譯器會把這個字符串中的內存(我猜堆棧),並創建一個指向它?這是如何工作的?

2-另外,如果它是在函數中本地創建的,函數返回時將釋放該字符串佔用的內存?

3-最後但並非最不重要的是,爲什麼不允許:ptr[0] = 'H';

+0

完成,我不知道那件事。 Thx – m4design 2010-06-02 19:26:46

回答

6

1)中的字符串是(堆棧上正常) - 它通常會在該真實直接從可執行文件讀取的初始化數據段。指針然後被初始化爲該字符串的地址。

2)號

3)由於標準說它給未定義的行爲。試想,如果你有這樣的事情:

int a() { char *a = "a"; printf("%s\n", a); } 
int b() { char *b = "a"; *b = 'b'; } 

int main() { 
    b(); 
    a(); 
    return 0; 
} 

現在,當你打印出來a,你希望得到的原始值(A)或更新的價值(二)?編譯器可以但不一定共享這樣的靜態字符串;有些還將整個區域標記爲只讀,因此試圖寫入它將會產生一個異常。

從C標準的角度來看,唯一合理的答案就是將其稱爲未定義的行爲。

1
  1. 編譯器會把指針內存中的串並放入指針字符串「喜」的地址。該字符串本身將位於程序的代碼圖像中。

  2. 指針的內存將被釋放。

  3. 由於您的代碼定義的ptr指向代碼圖像中的常量。你不能寫一個常量。

+0

2.指針的內存將被釋放,但該字符串的內存不會。如果你的函數被再次調用,字符串必須來自某處。 – 2010-06-02 19:27:22

2
  1. 編譯器會把字符串「喜」的地方在內存中(它不是由標準的開徵),而你不知道在哪裏,但你必須考慮到它可放置在內存的只讀部分(儘管它由編譯器決定)。然後會創建一個指針,指向開始到這個地方的內存。

  2. 內存不一定會被釋放,因爲在大多數情況下,這個字符串將駐留在內存的數據部分(與編譯指令相同的地方)。

  3. 這是不允許的,因爲標準不保證對這種自動分配的內存塊的寫入訪問權限(見1)。它可能適用於某些系統/平臺/編譯器,但不能由標準保證。

1
  1. 你可能會更準確,更穩健表達它:

    const char *ptr = "hi";

    不僅是actualité然後在你的代碼中表達,但是編譯器也將陷阱試圖寫由ptr指向的內存。字符串本身是一個「靜態常量」(因此不在堆棧中),指針是一個初始化爲字符串地址的變量。

  2. 不,只有第epointer將在堆棧上實例化。數據將保留在靜態常量內存中(通常作爲代碼文本段的一部分)。大多數編譯器/鏈接器工具鏈都會匹配常見的字符串,例如,如果在代碼中有幾個「hi」實例,那麼它們實際上都會引用同一個單一實例。

  3. 這是未定義的行爲。根據文本的存儲方式,它可能會或可能不會工作。現代處理器/操作系統通常實施保護機制來保護代碼段免受修改和執行;因爲這些字符串通常也在代碼段中,所以嘗試修改該字符串可能會導致運行時異常。在編譯時通過聲明指針const來檢測這個錯誤要好得多。

    如果您碰巧使用的是16位DOS編譯器或沒有內存保護的目標,它可能看起來有效;但由於可以整理常用字符串,因此您可能會修改由多個指針引用的字符串。在嵌入式目標中,字符串可能駐留在ROM中,在這種情況下,即使訪問未被捕獲爲非法,也不起作用。