#include <stdio.h>
int main() {
char *t = "hello world";
puts(t);
//printf("%s", t);
t = "goodbye world";
puts(t);
}
t的內存未分配,所以爲什麼我在運行時沒有出現段錯誤?指向C風格字符串的指針未分配
#include <stdio.h>
int main() {
char *t = "hello world";
puts(t);
//printf("%s", t);
t = "goodbye world";
puts(t);
}
t的內存未分配,所以爲什麼我在運行時沒有出現段錯誤?指向C風格字符串的指針未分配
內存是分配給t
;分配足夠的內存來存放指針(通常,32位程序中的4個字節,64位程序中的8個字節)。
此外,t
初始化確保指針指向的地方:
char *t = "hello world";
字符串字面也被分配空間,某處。通常,這是在內存的只讀部分,所以您應該真的使用const char *t = "hello world";
,即使您不使用明確的const
,也不應該嘗試修改指向t
的字符串。但編譯器的問題是確保t
指向某個有效的地方。
類似地,分配後:
t = "goodbye, Cruel World!";
該變量在由編譯器分配的空間定位。只要你不濫用它(而你的代碼沒有),這很好。
什麼會讓你陷入麻煩是這樣的:
char *t;
puts(t); // t is uninitialized; undefined behaviour
t = 0; // equivalently, t = NULL;
puts(t); // t contains the null pointer; undefined behaviour
的未初始化的局部變量可以包含任何價值;你無法可靠地預測會發生什麼。在某些機器上,它可能包含一個空指針並導致崩潰,但這不是你可以依賴的。
空指針並不指向任何有效的指針,因此解引用空指針會導致未定義的行爲,而且這種未定義的行爲通常是崩潰。 (經典的,在DEC VAX機器上,你在地址零處得到一個零字節而不是崩潰,這導致了(部分)Henry Spencer'sTen Commandments「全世界都不是VAX」 - 還有,「你不應該遵循空指針,混亂和瘋狂等待你的結尾。「)
所以,在你的程序中,內存分配給t
和t
被初始化並分配給指向(只讀)字符串常量,所以沒有理由的程序崩潰。
t是一個指針,所以你只是讓t指向另一個字符串。
由於字符串文字是靜態分配在您的程序存儲器中的 - 您不需要明確地爲它們分配內存。
編譯器需要爲t
分配的所有內存在32位系統上是4個字節。記住它只是一個指針。在前幾行中,它指向「hello world」,但在此之後,您將其更改爲指向「再見世界」。 C將爲您定義的字符串分配足夠的內存,並將指針傳遞給您,以便您可以指向它們。你不必擔心這一點。另請記住,這些字符串是靜態和只讀的,這意味着您不能安全地說t[4] = 'b';
。
你能說說爲什麼你會期望它出現段錯誤? –