2012-04-17 118 views
0

我想學習C指針,但得到夾雜了以下概念:理解指針

char *string = "hello" 
char *string2; 

之間的主要區別是什麼:

A.) *string2 = string; 

然後

B.) string2 = "bye"; 
+0

第二個錯誤。與指針無關,類型不匹配。 – littleadv 2012-04-17 08:14:19

+1

那麼,只要你學習指針,你可能會看到它:http://cslibrary.stanford.edu/104/ – dranxo 2012-04-17 08:28:34

+0

@diesel:我的答案(下面)更適用於編輯前提出的問題,但我因爲它涵蓋了現在被問得相當簡潔的概念。 – wallyk 2012-04-17 08:32:20

回答

0

編輯後:

不同之處在於A)不會編譯,如果是這樣的話,那麼它是未定義的行爲,因爲您要解引用未初始化的指針。

此外,發佈後請不要急於改變您的問題。

+0

@SteveJessop謝謝你。 – 2012-04-17 08:32:55

0

*string可以理解爲「無論string指向」,這是一個char。將"bye"分配給它是沒有意義的。

0

C字符串只是一個字符數組。 C字符串文字如上面的"hello"可以被看作是「返回」指向字符數組的第一個元素{ 'h', 'e', 'l', 'l', 'o' }的指針。

因此,char *string = "bye"是有意義的,而char string = "bye"沒有。

0

char *是指向一個字符的指針。文字如"hello"返回一個指向字符串第一個字符的指針。因此,string = "bye"是有意義的,使string指向字符串"bye"的第一個字符。

*string,在另一方面,是字符通過string指出。它不是一個指針,而是一個8位整數。這就是爲什麼賦值*string = "bye"沒有意義,並且可能導致段錯誤,因爲"bye"存儲的內存段是隻讀的。

3

其他回答者有一些微妙的推論,錯過了新手的POV。

char *string = "hello"; 

聲明一個指針變量,它被初始化爲指向一個字符數組(傳統上是一個好的類型匹配)。

聲明

*string = "hello"; 

解引用什麼應該是一個指針變量和分配值指示位置。 (它不是一個變量聲明;必須在某處完成)。但是,由於string的類型爲char * —所以*string的類型爲char —而賦值的右側是一個帶有指針值的表達式,類型不匹配。這可以固定在兩種方式,這取決於語句的意圖:

string = "hello";  /* with "char *" expressions on both sides */ 

*string = 'h';  /* with "char" expressions on both sides */ 

第一重新分配string爲指向包含字符序列(hello\000)存儲器。第二個作業將string指向的字符更改爲charh

無可否認,這是一個有點令人迷惑的科目,其中全部C程序員經歷了一點點痛苦學習掌握。 指針聲明語法與語句中的相同文本略有不同(但相關)的效果。獲得更多的練習和體驗寫作和編譯涉及指針的表達式,最終我的話將是完美的。

7

有些圖片可能會有所幫助。

假定以下的存儲器映射(地址是完全任意的,並不反映任何已知的體系結構):

 
Item   Address   0x00 0x01 0x02 0x03 
----   -------   ---- ---- ---- ---- 
"hello"   0x005'h' 'e' 'l' 'l' 
       0x005'o' 0x00 
"bye"   0x0050123A      'b' 'y' 
       0x0050123C   'e' 0x00 0x?? 0x?? 
       ... 
string   0x80FF0000  0x00 0x50 0x12 0x34 
string2   0x80FF0004  0x?? 0x?? 0x?? 0x?? 

這顯示了聲明之後的情況。 "hello""bye"是字符串文字,作爲char「內存」的數組存儲在內存中,以便它們在程序的整個生命週期內都可用。請注意,嘗試修改字符串文字的內容會調用未定義的行爲;你不想(計算結果爲字符串常量的地址或指針這樣的表達式string)字符串文字作爲參數傳遞給函數一樣scanfstrtokfgets

string是指向char,含字符串文字的地址"hello"string2也是指向char的指針,其值不確定(0x??表示未知的字節值)。

當你寫

string2 = "bye"; 

"bye"(0x0050123A)的地址分配給string2,所以我們的內存映射現在看起來是這樣的:

 
Item   Address   0x00 0x01 0x02 0x03 
----   -------   ---- ---- ---- ---- 
"hello"   0x005'h' 'e' 'l' 'l' 
       0x005'o' 0x00 
"bye"   0x0050123A      'b' 'y' 
       0x0050123C   'e' 0x00 0x?? 0x?? 
       ... 
string   0x80FF0000  0x00 0x50 0x12 0x34 
string2   0x80FF0004  0x00 0x50 0x12 0x3A 

看起來很簡單,對不對?

現在讓我們來看看

*string2 = string; 

有幾個問題在這裏聲明。

首先,一個題外話 - C中的聲明集中在表達式的類型中,而不是對象。string2是一個指向字符的指針;訪問字符值,就必須解引用string2與一元*操作者:

char x = *string2; 

的類型表達*string2char,所以聲明變得

char *string2; 

通過擴展, 表達式的類型string2char *或指向char的指針。

所以,當你寫

*string2 = string; 

你試圖型char *string)的值賦給char類型(*string2)的表達。這是行不通的,因爲char *char是不兼容的類型。這個錯誤出現在翻譯(編譯)時間。如果你寫了

*string2 = *string; 

那麼這兩個表達式的類型都是char,而賦值是合法的。

但是,如果您還沒有爲string2分配任何東西,它的值是不確定的;它包含一個隨機位串,它可能對應或不對應有效的可寫地址。試圖推斷隨機的,可能無效的指針值會引發未定義的行爲;它可能看起來工作正常,它可能會崩潰,它可能會做任何事情之間。這個問題直到運行時纔會顯示出來。更好的是,如果您將字符串文字"bye"指定爲string2,則會遇到上述問題;你試圖修改字符串文字的內容。再次,這是一個問題,直到運行時纔會顯示出來。