2012-03-27 122 views
4

讓我們說我們有一個指針數組:c char字符指針

char *ptr[30];

現在這工作得很好,並且似乎並不做任何意外! 我可以很容易地輸入名字。

scanf("%s", ptr[1]); 
scanf("%s", ptr[2]); 
scanf("%s", ptr[3]); 

printf("%s\n", ptr[1]); 
printf("%s\n", ptr[2]); 
printf("%s\n", ptr[3]); 

我的問題是,如果一個指針可以通過這種方式來儲存姓名結束的數目使用,那麼爲什麼使用malloc的?在這種情況下,ptr [1]不會指向輸入中的字符,而是指向新的輸入本身。 例如,如果ptr有mukul,ptr [1]應該指向'u' ,並且如果在像這樣聲明指針時沒有分配空間,那麼限制是什麼。

+7

此外,必須注意,數組中的第一個元素是ptr [0]。 – SirDarius 2012-03-27 12:21:36

+0

嘗試在'scanf's和'printf'之間做一些事情。你應該看到一些未定義的行爲。 – stanwise 2012-03-27 12:23:05

+0

耶ptr [0]肯定有!感謝您的回覆! – 2012-03-27 12:45:38

回答

13

指針不能用這樣使用。它有時可能「爲你工作」,有時只是偶然,但使用指針而不爲其分配內存將導致undefined behavior - 這意味着你的程序可能表現不正常,並給你意想不到的結果。

記住,只是因爲你的程序編譯並運行並不意味着它是正確的。在C語言中,有一整類錯誤稱爲「未定義行爲」,其中許多編譯器會樂於讓您無需抱怨。這些包括覆蓋緩衝區,使用未初始化的變量,或取消引用不指向合法分配的內存塊的指針。展現未定義行爲的程序有時甚至可能會正常工作 - 但它們通常非常不穩定並且容易崩潰。

+0

謝謝你的回答! – 2012-03-27 12:39:54

+2

也請告訴該聲明char * ptr [30],告訴有30個字符指針,即它可以指向30個不同的字符,因爲它是一個指針數組或它可以指向30個不同的字符數組(在這種情況下名稱) ? – 2012-03-27 12:41:12

+0

我的意思是它應該指向30個不同的字符,但在這裏它被用來指向30個不同的名字,這是正確的。? – 2012-03-27 12:41:59

4

如果您使用示例中的內容,則只需在ptr陣列後寫下其他位置的內容。大多數編譯器實際上應該至少給出一個警告。你的程序會在大多數系統上崩潰,你很幸運。

+0

非常感謝先生! – 2012-03-27 12:55:55

3

當你定義像是指針:

char *ptr = 0; // NULL pointer: dereferencing it will crash 
puts(ptr); // crash 

你只是在內存中創建一個鏈接到一個地方:

ptr = "string"; // dereferencing it will show the string 
puts(ptr);  // displaying "string" 

因此具有指針數組只是創建到其他的引用列表變量。

若要引用內存中的某個位置,您必須將然後分配變量到您的指針,或爲每個指針分配內存。

+0

所以一個指針說char * c;可以指向一個字符,或者它可以指向一個字符數組.. ..?什麼更正確?如果它只指向一個字符,然後再做C++並再次存儲,它應該覆蓋! – 2012-03-27 12:44:40

+0

一個指針可以指向任何大小的數據,不一定指向同一類型的指針。目標是否爲數組取決於您。變量是記憶的地方。指針是對內存的引用。 – Gil 2012-03-27 12:47:32

+0

這是正確的,但做指針++應該始終指向下一個內存位置。如果一個數組已經存儲在前一個位置,這個位置應該被處理? – 2012-03-27 12:50:47

3

您已經爲30個指針分配了空間,但您尚未初始化它們以指向任何有意義的地方。除非您在函數之外聲明數組,否則數組中的每個元素都將包含一些隨機位串,這些隨機位串可能對應於可寫內存位置,也可能不對應。如果我們畫了一幅畫,它看起來像這樣(所有地址都是無中生有的,不承擔此相對應的任何真正的架構):

 
Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
ptr  0xbbc81230 0x?? 0x?? 0x?? 0x?? 
      0xbbc81234 0x?? 0x?? 0x?? 0x?? 
      0xbbc81238 0x?? 0x?? 0x?? 0x?? 
      ... 
      0xbbc812a8 0x?? 0x?? 0x?? 0x??   

其中0x??代表一個隨機字節值。對於你所描述的行爲,每個隨機值只是發生在指向可寫內存,並寫在那裏存儲的任何東西只是發生沒有任何直接的不良影響。

壞朱朱:它看起來你的代碼工作正常,而實際上它的表現非常糟糕,並可能導致在你的程序有些討厭的運行在其他地方的問題,是一個痛苦的調試。

您需要明確設置ptr陣列的每個元素,以在嘗試通過它寫入之前指向有效的內存位置。

假設我們添加以下代碼:

ptr[0] = malloc(strlen("foo") + 1); 
strcpy(ptr[0], "foo"); 
ptr[1] = malloc(strlen("bar") + 1); 
strcpy(ptr[1], "bar"); 

我們動態地分配一些額外的內存來容納一對夫婦的字符串,並將其存儲在指向這些新緩衝區ptr[0]ptr[1]

我們的圖片現在看起來是這樣的:

 
Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
      0x80ff0000  'f' 'o' 'o' 0x00 
      ... 
      0x80ffcdc0  'b' 'a' 'r' 0x00 
      ... 
ptr  0xbbc81230 0x80 0xff 0x00 0x00 
      0xbbc81234 0x80 0xff 0xcd 0xc0 
      0xbbc81238 0x?? 0x?? 0x?? 0x?? 
      ... 
      0xbbc812a8 0x?? 0x?? 0x?? 0x??   

ptr[0]現在包含大小,以容納4個char值的緩衝區的地址,我們將字符串「foo」複製到緩衝區。同樣,ptr[1]包含另一個4字節緩衝區的地址,該緩衝區現在包含字符串「bar」。