我已經定義了一個函數,它有一個指向char的指針作爲它的參數。當將一個常量字符串傳遞給此函數的指針時,該字符串是否在內存中保留了一個專用空間,或者是否有其他對象可以覆蓋它,而無需使用指針訪問此指定空間?向指針指定字符串時是否保留空間內存
定義我的功能
void myFunction(char *p){
// some instructions
}
傳遞一個字符串常量此功能
myFunction("Some Text");
我已經定義了一個函數,它有一個指向char的指針作爲它的參數。當將一個常量字符串傳遞給此函數的指針時,該字符串是否在內存中保留了一個專用空間,或者是否有其他對象可以覆蓋它,而無需使用指針訪問此指定空間?向指針指定字符串時是否保留空間內存
定義我的功能
void myFunction(char *p){
// some instructions
}
傳遞一個字符串常量此功能
myFunction("Some Text");
真的,你應該寫void myFunction(const char *p){
監守,無論你做什麼,不要試圖修改字符串指向由p。要做到這一點是未定義的行爲。
這是因爲字符串"Some Text"
將在程序編譯時被複制到只讀存儲器中,並且指向它的指針將被傳遞到p
。
不,它不爲字符串分配內存,將字符串開始的指針壓入堆棧,如果嘗試修改字符串,則會發生段錯誤,但可以修改指針。
該調用會將字符串的地址傳遞給該函數,並且該地址在編譯時(或程序啓動時的動態鏈接時間)是固定的,但從這個問題的角度來看,它是相同的) 。如果某些事情試圖修改該內存地址的內容,那麼操作系統將取決於發生了什麼情況。在許多(大多數?)現代PC操作系統中,字符串文字將位於只讀存儲器區域,如果應用程序試圖修改它,則會出現分段錯誤。在其他(舊的,嵌入式等)操作系統或CPU體系結構中,可能甚至沒有辦法讓某些內存只讀,然後可以修改字符串文字,但它可能仍然會導致意想不到的結果(請參見下一段)。 修改字符串文字是C標準中的未定義行爲。
記憶是「專用的」是否是解釋的問題。如果您有兩個字符串文字,如"foobar"
和"bar"
,則允許編譯器使它們重疊,因此"foobar"
文字指向'f',而"bar"
文字指向同一存儲器空間中的'b'。除非你正在做一些非常「聰明」的指針比較,否則這應該沒有什麼區別,因爲它們都在只讀內存中。
有一些方法可以修改字符串:可以編寫以內核特權運行的代碼,這可以在程序運行時修改該「只讀」內存的內容。也可以改變編譯器,使字符串文字不在只讀存儲器中,然後可以修改它們而不會造成程序崩潰。對於非運行時永久性更改,可以使用十六進制編輯器簡單編輯程序二進制文件並更改字符串。但在定期開發應用程序時,這些都不是問題。
一般來說,如果你傳遞一個指針在C(或C++,其中適用於過引用)的功能,總是讓一個指針爲const(或C++ const引用),如const char*
在這個案例。調用者可能有一個const對象,並且你不想阻止他們用這個函數調用函數。如果函數實際上要修改參數,那麼你希望編譯器停止調用者傳遞一個const對象給它。
我選擇使用「char * p」而不是「const char * p」,因爲我可能會將數組的地址傳遞給指針而不是「字符串文字」。 – rullof
在這種情況下,在函數原型中使用'const char p'仍然可以:'p'將是第零個數組元素。 – Bathsheba
@rullof如果你不打算修改字符串,* always *使C函數參數爲'const char *'。這實際上適用於每個指針,而不僅僅是'char *'。調用者可能有一個指向const的指針,並且你不想阻止他們用這個函數調用函數,除非你真的要修改它指向的內容。 – hyde