2010-10-09 86 views
3

可能重複:
What is the difference between char s[] and char *s in C?試圖瞭解指針和數組

我想知道是什麼

char *p1 = "some string"; 

char p2[] = "some string"; 
之間的區別

就內存而言,這些不能用同樣的方式處理?

例如

void foo(char *p); 

...

foo(p1); 
foo(p2); 
+0

[C中char s \ [\]和char * s有什麼區別?](http:// stackoverflow。com/questions/1704407/char-s-and-char-s-in-c之間的區別) – 2010-10-09 01:29:39

+0

指針與數組是一個廣泛的議題。關於這些差異有很多要說的地方,我通常會開始踢球,因爲在平均SO帖子中不可能給出論證正義。 – 2010-10-09 01:35:42

+0

我只是有興趣瞭解它。 – user470779 2010-10-09 01:38:04

回答

0

P1是一個指針 - 所以你可以做指針運算,像P1 ++

P2是一個數組,固定長度。你可以做一個sizeof(p2),它將返回12 你不能做p2 ++,也就是指針算術。

+0

但是對於函數'foo'它會在兩種情況下都有一個指針來使用?即使它傳遞了一個數組| |指針 – user470779 2010-10-09 01:31:53

+1

是的,無論哪種方式,該函數都有一個要使用的指針。但請注意,該函數不得嘗試修改由'p1'指向的字符串。 – RBerteig 2010-10-09 01:34:09

0

前者在只讀存儲器中放入「一些字符串」,並將p1作爲指向該字符序列的第一個字符的指針。您可以將p1的值更改爲指向其他任何地方。

後者爲堆棧上的p2保留空間並將其內容存儲爲「某些字符串」。您可以更改堆棧中的各個位置,但不能更改p2的值。例如,

p2 = "a new string" ; 

是C.未定義的行爲當p2爲在賦值語句(我忘記在C標準中使用的措辭)的右側,它充當的第一個元素的地址數組(指向char的類型指針)。

(6.3.2.1節,第3段)「除了當它是sizeof操作或一元&操作者的操作數,或是用於初始化數組文本的字符串,其具有輸入‘’的表達式類型''的數組被轉換爲類型爲''指向類型''的指針,該指針指向數組對象的初始元素,並且不是左值。「

0
char *p1 = "some string"; 

你把字符指針在堆棧中。這需要大約4個字節的內存(但可能不同)。然後您將其設置爲靜態存儲器位置的地址。 這句話的正確形式是:

char const *p1 = "some string"; 

由於這種強制執行該字符串的內容是不變的。

char p2[] = "some string"; 

您正在棧上聲明一個大小爲12(字符串長度加nul)的數組。這是12個字節的數據。您可以修改數組的內容,但不能將其作爲參數傳遞時降級到的指針更改爲或指定給char *。

有兩個報表主要差異:

p1 = new char[50]; // legal 
p2 = new char[50]; // illegal 

p1[2] = 'a'; // illegal 
p2[2] = 'a'; // legal 

當作爲參數傳遞給函數,變量的樣子:

char const *p1; // this is what p1 is 
char *const p2; // this is what p2 degrades to. It is a const pointer to the first element. 
0

它們彼此相關,但有一個巨大差距。

char p2[] = "some string"; 

要求用於12個字符的空間和由名稱p2已知的。在另一方面:

char *p1 = "some string"; 

詢問持有一個名爲p1它可以指向任何地方指針的地方。在這種情況下,指針p1指向一個沒有名稱的數組或一個包含12個字符的匿名數組。該匿名數組存在內存中,並且指針p1正在跟蹤其位置。

0

在你的第一種情況下,...

char* p1 = "some string"; 

... p是指針類型,char*的變量。它被初始化爲指向某個地方的char值序列中的第一個char。那個地方可能只有只讀內存,所以你不應該這樣做:-)。

相反,至少添加const爲指針對象的類型,比如......

char const* p2 = "some string"; 

這樣,你問的編譯器不接受修改的嘗試,這將送你未定義行爲的土地。 C++接受p1的聲明,只有與C的向後兼容性。如果你打開C++編譯器的警告級別,你很可能會得到一個關於它的警告,而p2的聲明是非常好的。

由於p2不是const本身,您可以修改它,例如,增加它,使其指向第二個char,或其他。

無論如何,指針並不是很大,通常是4或8個字節。

在第二個情況下,...

char a[] = "some string"; 

... a是用指定字符初始化一個數組,加上終止空字節。每個定義的每個char是一個字節。 sizeof(a)因此會報告a是12個字節,即指定字符的11個字節加上空字節。

在C和C++,在使用a其中指針被預期,則得到一個自動轉換爲指針第一陣列元件,和我們非正式地說,陣列衰變到指針類型。在C中,這發生在所有將數組作爲參數傳遞的情況下。然而,在C++中,您可以通過引用來傳遞數組,從而避免類型衰減。

使用衰減到優點,可以發現通過該陣列的元件的數量...

sizeof(a)/sizeof(*a) 

所述分割是不必要的字節數組,如a是,但有必要在一般用於其他類型的數組。

如果你用指針做這件事,那麼你只需要得到指針大小單位的指針大小,這很少有意義。

在C中沒有其他合理的方法來查找數組元素的數量,所以上面的表達式通常打包在一個宏中,並且只是接受無意中使用帶有指針參數的宏的風險(無意義的結果)。

在C++中可以使用通過引用傳遞數組定義返回一個數組,像元素的數量的函數的可能性...

typedef ptrdiff_t Size; 

template< class T, Size N > 
Size countOf(T const (&)[N]) { return N; } 

countOf調用用指針作爲實際參數你只會得到一個編譯錯誤而不是無意義的結果。

對於C++工作,定義startOfendOf函數通常也很方便,特別是使用標準庫中的算法。據我所知,第一個承認這個三位一體功能重要性的人是Dietmar Kuhl。你可以在我的WordPress博客上找到a general implementation,但不幸的是,我記得,我沒有在那裏提到Dietmar(我懶得修理東西!:-))。

C++對C沒有的數組也有一些其他的支持。

特別是,作爲新手,您通常會更好地使用標準庫中的std::vector,而不是直接使用「原始數組」。

使用std::vector你不太可能遇到與原始數組相關的許多缺陷,例如,元素數量計算。

乾杯& HTH,

- 阿爾夫

0

p1是一個指針。 p2是一個數組,在表達式中使用時,該數組的值爲一個指針。

也許一個比喻是爲了:

int x1 = 5; 
char x2 = 5; 

x1intx2char,當在表達式中使用時,其計算結果爲int

在這兩種情況下,當您嘗試在對象中存儲某些內容以及將sizeof運算符應用於它們時,差異就會變得明顯。