我想學習C指針,但得到夾雜了以下概念:理解指針
char *string = "hello"
char *string2;
之間的主要區別是什麼:
A.) *string2 = string;
然後
B.) string2 = "bye";
我想學習C指針,但得到夾雜了以下概念:理解指針
char *string = "hello"
char *string2;
之間的主要區別是什麼:
A.) *string2 = string;
然後
B.) string2 = "bye";
編輯後:
不同之處在於A)不會編譯,如果是這樣的話,那麼它是未定義的行爲,因爲您要解引用未初始化的指針。
此外,發佈後請不要急於改變您的問題。
@SteveJessop謝謝你。 – 2012-04-17 08:32:55
*string
可以理解爲「無論string
指向」,這是一個char
。將"bye"
分配給它是沒有意義的。
C字符串只是一個字符數組。 C字符串文字如上面的"hello"
可以被看作是「返回」指向字符數組的第一個元素{ 'h', 'e', 'l', 'l', 'o' }
的指針。
因此,char *string = "bye"
是有意義的,而char string = "bye"
沒有。
char *
是指向一個字符的指針。文字如"hello"
返回一個指向字符串第一個字符的指針。因此,string = "bye"
是有意義的,使string
指向字符串"bye"
的第一個字符。
*string
,在另一方面,是字符通過string
指出。它不是一個指針,而是一個8位整數。這就是爲什麼賦值*string = "bye"
沒有意義,並且可能導致段錯誤,因爲"bye"
存儲的內存段是隻讀的。
其他回答者有一些微妙的推論,錯過了新手的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
指向的字符更改爲char
值h
。
無可否認,這是一個有點令人迷惑的科目,其中全部C
程序員經歷了一點點痛苦學習掌握。 指針聲明語法與語句中的相同文本略有不同(但相關)的效果。獲得更多的練習和體驗寫作和編譯涉及指針的表達式,最終我的話將是完美的。
有些圖片可能會有所幫助。
假定以下的存儲器映射(地址是完全任意的,並不反映任何已知的體系結構):
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
)字符串文字作爲參數傳遞給函數一樣scanf
,strtok
,fgets
等
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;
的類型表達*string2
是char
,所以聲明變得
char *string2;
通過擴展, 表達式的類型string2
是char *
或指向char
的指針。
所以,當你寫
*string2 = string;
你試圖型char *
(string
)的值賦給char
類型(*string2
)的表達。這是行不通的,因爲char *
和char
是不兼容的類型。這個錯誤出現在翻譯(編譯)時間。如果你寫了
*string2 = *string;
那麼這兩個表達式的類型都是char
,而賦值是合法的。
但是,如果您還沒有爲string2
分配任何東西,它的值是不確定的;它包含一個隨機位串,它可能對應或不對應有效的可寫地址。試圖推斷隨機的,可能無效的指針值會引發未定義的行爲;它可能看起來工作正常,它可能會崩潰,它可能會做任何事情之間。這個問題直到運行時纔會顯示出來。更好的是,如果您將字符串文字"bye"
指定爲string2
,則會遇到上述問題;你試圖修改字符串文字的內容。再次,這是一個問題,直到運行時纔會顯示出來。
第二個錯誤。與指針無關,類型不匹配。 – littleadv 2012-04-17 08:14:19
那麼,只要你學習指針,你可能會看到它:http://cslibrary.stanford.edu/104/ – dranxo 2012-04-17 08:28:34
@diesel:我的答案(下面)更適用於編輯前提出的問題,但我因爲它涵蓋了現在被問得相當簡潔的概念。 – wallyk 2012-04-17 08:32:20