2012-08-26 69 views
2
#include <stdio.h> 

int main() { 
    char *t = "hello world"; 
    puts(t); 
    //printf("%s", t); 
    t = "goodbye world"; 
    puts(t); 
} 

t的內存未分配,所以爲什麼我在運行時沒有出現段錯誤?指向C風格字符串的指針未分配

+2

你能說說爲什麼你會期望它出現段錯誤? –

回答

2

內存分配給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」 - 還有,「你不應該遵循空指針,混亂和瘋狂等待你的結尾。「)

所以,在你的程序中,內存分配給tt被初始化並分配給指向(只讀)字符串常量,所以沒有理由的程序崩潰。

4

t是一個指針,所以你只是讓t指向另一個字符串。

4

由於字符串文字是靜態分配在您的程序存儲器中的 - 您不需要明確地爲它們分配內存。

2

t這裏是一個指向匿名字符串的第一個字符的指針,它可以在只讀內存中。一個好主意是指針的指針申報const char

const char *t = "hello world"; 

又見here

+0

不錯的鏈接。但是你確定只讀內存嗎? – Rsh

+2

字符串文字通常位於只讀數據段 – md5

+1

字符串文本不僅具有'靜態'持續時間,它們也正式是隻讀的(const),因此,正如你在答案@ArashThr中所說的那樣,你不應該嘗試去修改一個字符串,原因之一是它可能在只讀內存中,並且試圖修改它會引發碰撞;另一個如果它在可修改的內存中並且您修改它,它將在程序期間保持修改。 –

2

編譯器需要爲t分配的所有內存在32位系統上是4個字節。記住它只是一個指針。在前幾行中,它指向「hello world」,但在此之後,您將其更改爲指向「再見世界」。 C將爲您定義的字符串分配足夠的內存,並將指針傳遞給您,以便您可以指向它們。你不必擔心這一點。另請記住,這些字符串是靜態和只讀的,這意味着您不能安全地說t[4] = 'b';