2015-03-31 96 views
16

我是編程新手。我正在學習C作爲我的第一種編程語言。我發現了一些奇怪的理解。瞭解字符數組[]和字符串

我已經學會在C我們可以表示一個字符串作爲像這樣的字符(使用字符數組)的序列:

char status[10] = "Married"; 

我已經瞭解到,這種方法的問題是,我們不得不在編譯期間告訴status陣列的大小。

但現在我已經學會了,我們可以用一個char指針來表示一個string像 -

char status[10] = "Married"; 
char *strPtr; 
strPtr = status; 

我不正確地理解它。我的問題是 -

  1. 我怎樣才能在焦炭指數4(即已婚)使用strPtr

  2. status有在由char陣列表示的string的端部的空字符(\0) - M - a - r - r - i - e - d - \0。所以通過使用空字符(\0)我們可以理解字符串的結尾。當我們使用strPtr時,我們如何理解string的結束?

+2

1)'*(strPtr + 4)'會給你char'i'。 2)'strPtr'也指向'status',所以它末尾會有(相同的)空字符('\ 0')。 – 2015-03-31 10:48:32

+2

由於數組衰減到指向其第一個元素的指針,因此數組和指針通常可以互換使用,因此在數組上使用解引用操作符將會起作用,就像在指針上使用數組索引操作符一樣。另外,'*(arrayOrPointer + X)'相當於'arrayOrPointer [X]'。 – 2015-03-31 10:48:37

+0

檢查[sizeof(&array)'返回什麼?](http://stackoverflow.com/questions/15177420/what-does-sizeofarray-return/15177499#15177499) – 2015-03-31 16:09:04

回答

12
char *strPtr; 
strPtr = status; 

現在你的指針strPtr所指向的第一個字符數組中,你可以做

int i =0; 
while(strPtr[i] != '\0') 
{ 
    printf("%c ",strPtr[i]); 
    i++; 
} 

*strPtr被稱爲解引用指針獲取存儲在該位置的指針值指向。

請記

strPtr[4] = *(strPtr +4); 

都將讓你存儲在數組的索引4處的值。

注意指針和數組名之間的區別:

---------------------------------- 
| s | t | r | i | n | g | \0 | 
---------------------------------- 
    | 
strPtr 
status 

strPtr ++會讓你的指針指向數組中的下一個元素。

| s | t | r | i | n | g | \0 | 
---------------------------------- 
     | 
     strPtr 

而不能用於數組名

status++這樣做是不允許的,因爲an array is not a modifiable lvalue

+0

哇!那意味着我們可以使用指針名稱'strPtr'作爲數組?我現在會嘗試。感謝您的回覆。 – KajolK 2015-03-31 10:51:41

+0

@KajolK檢查編輯以獲得數組與指針之間的差異 – Gopi 2015-03-31 10:57:15

+0

在C中,數組索引僅僅是加法之後指針的解引用:'x [i]'意味着'*(x + i)'。 – 2015-03-31 15:57:09

1

字符串末尾的'\ 0'是一個無用的附加組件,用於簡單或安全。您可以通過使用 '的sizeof' 這樣告訴字符串最後一個字符:

char status[] = "Married"; 

size_t szLastCharstatus = sizeof(status)/sizeof(status[0]) - 2; 

char chLastChar = status[szLastCharstatus]; 

詳細說明:

sizeof(status) 

返回的字節數組occpuies數。

sizeof(status[0]) 

返回第一個元素佔據的字節數(等等)。

這兩個值之間的劃分給了我們數組中元素的數量。爲了訪問最後一個元素,我們需要減去2次,因爲數組中的元素從零開始計數,因爲字符串中的最後一個字符是'\ 0'。

另請注意,數組不是指針,反之亦然。數組有一個隱式轉換爲它們第一個元素的指針,常量大小和它們自己的類型。它們可以通過指針或值來傳遞(第二個需要使用結構攻擊)。

請注意,我正在使用'size_t',它是存儲某種大小數據的變量的類型變量。

+0

這將給出數組中元素的數量,但不包含數組中包含的字符串的長度。由於只有8個字符被初始化,最後兩個字符會有不確定的值,讀取它們會導致未定義的行爲。還要注意,這隻適用於「正確的」數組,一旦數組衰減到指針,sizeof'技巧將不再起作用。終結符字符並非無用,所有標準的C字符串函數都依賴於它。 – 2015-03-31 10:52:43

+1

還要注意,問題標籤爲'C',所以沒有'std'命名空間。 – 2015-03-31 10:53:11

+0

@Joachim Pileborg然而,它有時是性能成本,避免它需要複雜的語法。只要數組通過值或指針傳遞,技巧就會工作。 也修復爲'C'。 – AnArrayOfFunctions 2015-03-31 11:07:24

3

表達式status[10]僅僅是*(status+10)的語法糖。

\0終止引擎蓋下用來檢查結束時,如果你自己實現一些字符串處理函數,你可以這樣做太,或者你可以忽視它,使用與這些字符串給出了一些其它參數size,或你可以(不要)選擇其他任何東西作爲終止符號。

這不僅僅是char數組或字符串的真實情況,C數組只是一個指向連續塊類似類型的東西的指針,編譯時檢查你的'數組'下標是不是超越宣佈時指定的「終點」。用*(array+offset)表示法,你需要自己檢查一下。

+0

@MattMcNabb'status [10]'在這裏不是未定義的行爲;該標準定義了取消引用_過去_數組的最後一個元素。 – 2015-03-31 15:54:51

+0

@BlacklightShining它只定義瞭如果在該位置保證分配內存(和其他一些條件爲真),'char status [10]不是這種情況;' – 2015-03-31 19:59:10

+0

' status [10]'表示與*(status + 10)'相同的東西在任何地方都被問到。 – Hurkyl 2015-04-25 21:48:43

4

好消息:

char status[10] = "Married"; 

是等效的只是語法糖

char status[10]; // allocate 10 Bytes on stack 
status[0] = 'M'; 
status[1] = 'a'; 
... 
status[6]= 'd'; 
status[7] = '\0'; // same as 0 

僅此而已,無所不及。

另外:

char c = status[3]; 

正是一樣

char c = *(status+3); 
+0

除了'new'不在這裏動態分配內存,所以它應該是'new(在.data或.rodata中的某個地址)char [10];' – myaut 2015-03-31 10:54:11

+1

我不確定,c中是否有'new'關鍵字?或者我應該不得不爲此使用C++? – KajolK 2015-03-31 10:54:51

+0

@KajolK:現在C中有'new'。如果你想動態地分配字符串,你需要'malloc()'。 – che 2015-03-31 10:56:13

2

要在指數4 strPtr得到的性格,你只需要使用strPtr[4](這也爲status工作)。

要使用strPtr時得到字符串的結尾,您需要瀏覽字符並查找終止的\0。這是printf("%s", strPtr)在打印字符串時(以及解析"%s"表達式時,它只是另一個字符串)所做​​的。要在C中的字符串中查找多個有效字符,請使用strlen()函數。噢,並確保你不要做這樣的事情:

char a[3]; 
strcpy(a, "Hello!"); 

由於這會寫7個字節到三字節的存儲空間,因此覆蓋你不想要的東西覆蓋。

2

我要做一個挑釁性的陳述:想想這個的方法是C沒有字符串C只有數組char。儘管它的名字,char實際上是一個數字類型(例如,'A',只是一個有趣的方式來寫一個數字,通常是65)。

char的數組與int或任何其他數組類型的數組並沒有真正的不同;只是該語言提供了一些額外的方式來編寫char類型的對象及其數組,並且存在一個通用約定(系統化爲具有諸如strlen之類的函數),用於如何將存儲在char數組中的數據解釋爲字符串的表示。

char status[10];  // declares an array of `char` of length 10. 
char *strPtr;  // declare a pointer to `char` 
strPtr = status;  // make `strPtr` point to the first element of `status` 

// Declare an array of 6 `char`, and initialize it. 
char hello[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; 

// Shorthand notation for initializing an array of 6 `char` as above 
char world[6] = "World"; 

// I want to store numeric data in this one! 
char other[6] = {0, 1, 2, 3, 4, 5}; 

// "World" is shorthand for a constant array of 6 `char`. This is 
// shorthand for telling the compiler to actually put that array in 
// memory someplace, and initialize worldPtr to point to that memory. 
const char *worldPtr = "World"; 

// This does the same thing as above. But it's still a *constant* array. 
// You should *never* do this; it should be syntactically illegal to 
// make a nonconstant `char*` to point to it. This is only allowed for 
// historical reasons. 
char *helloPtr = "Hello";