2011-10-04 137 views
2

我玩的指針和一個不能明白爲什麼這個聲明是好的關於指針聲明

char *ptr = "Hey" 

,但這是錯誤的

int *ptr = 10; 

任何一個能解釋一下嗎?

回答

7

正確的類比是,下面的兩個是錯誤:

char * p = 'a'; // error 
int * q = 123; // error 

在這裏,你正試圖某種類型的值賦給一個變量,它是一個指針到的變量那種類型。

與此相反,以下是正確的:

int tmp_a[] = { 10, 20, 30 }; 
char tmp_b[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; 

int * p = tmp_a; 
char * q = tmp_b; 

的字符串文字"hello"是字符的匿名,只讀陣列的相同的​​內容,作爲tmp_b,因此它可以被解釋爲一個指向其第一個元素。由於字符數據爲只讀,正確的定義應該是這樣的:

const char * r = "hello"; // r[0] - r[5] have the same value as q[0] - q[5] 
+0

應該明確指出,字符串文字(在C中)是隻讀的,但是不是「const」。這可能是一件壞事,只存在於舊代碼中,而C++則修復它。 –

+0

@ChrisLutz:你說得對,''hello''的*類型*只是C中的'char [6]'而不是'const char [6]',但是任何修改元素的嘗試都是UB - 所以最好立即聲明它爲const。不過,我會將其編輯爲「應該」。 –

+0

這個工具會自動生成C指針語法的解釋(它對此有用):http://cdecl.org/ –

1

C中的字符串被定義爲char *。否則,如果你想有一個單一的字符,你會使用char var = 'x';

int *ptr = 10;「錯誤」,它在法律上設置你的指針指向的地址「10」,這是在大多數(如果不是全部)的情況下,你的應用程序的內存界。

+0

這並不完全正確。 – Skizz

+0

這並不回答這個問題。 –

+0

不,將一個整型常量(0除外)隱式轉換爲指針類型是錯誤的。 –

4

簡單地說10不是int*,而是它是int。你不能指定一個int指針,因爲它們是不同的東西。

代碼char *ptr = "Hey"成功,因爲字符串文本與char*指針兼容。

但請注意,char *ptr = "Hey"會使ptr指向字符串文字。字符串文字通常存儲在只讀存儲器中,所以任何修改它們的嘗試都會失敗。所以你最好寫const char *ptr = "Hey"

0

在C,"Hey"被定義爲字符的一個匿名數組,所以內存被分配以存儲字符值(其中四個,還有一個空終止符)。

此外,你只能指向內存中的東西。所以char *可以指向匿名字符數組。

10只是一個值。它沒有分配給它的內存。你不能得到不在內存中的東西的地址。所以int *失敗。

要獲得第二工作,你需要分配一些內存:

int value = 10; 
int *ptr = &value; // value is in memory so we can point to it 
0

在第一種情況下,"Hey"是一個字符串,它的類型是char *。因此,以這種方式初始化ptr即可。話雖如此,它真的應儘可能遵循字符串文字不能被寫入:

char const * ptr = "Hey"; 

在另一方面,聲明是這樣的:

int * ptr = ...; 

你定義指向一個整數的指針。由於10是一個純整數常量,它不是一個現有的int對象,所以不能指向它。

int intValue; 
int * ptr = &intValue; 

在這種情況下intValue是一個對象,你可以指向:但是,你可以像寫些東西。

0

請記住像"Hey"這樣的字符串文字很特別。它們存儲在內存中的某個地方,並且是不變的。

指定一個指向"Hey"的指針實際上會在常量中創建該字符串,並將該常量的地址賦值給ptr

但是,當你有一個int* ptr,分配給10將分配地址10,而你的意思的價值10整數的地址。

0

說得很簡單。當編譯器看到的

char *ptr = "Hey" 

字符串「嘿」,編譯器會保存字符嘿加內存中的一個零終止字節,然後它會用一個指針代替「嘿」字符串的第一個字符中串。

int *ptr = 10; 

也不會在10轉換爲指針。它會將10看作一個整數,並且抱怨它不是ptr的類型 - 一個指向int的指針。