2014-09-30 94 views
0

我剛剛在我的大學開始了一門新課程,它沒有學習所有的語法和語義(這並不算太糟)。然而,與我理解的語言(java,python)相比,一個很大的區別是指針的概念。理解C中字符串的指針

我知道:

& - Address of something 
* - value stored at the address of something 

所以,如果我有這樣的字符串:

char a[] = "ABCDEF"; 

是 'A' 與它關聯的地址(&一),如果我這樣做(* a)它是否引用整個字符串? '數組'(A)中的第一個字符?

想想看看它是一個char [],字符串中的每個單個字符都有自己的地址嗎?

我最終的目標是編寫一個函數,該函數可以操縱指針,以便找到與第二個字符串中的字符匹配的一個字符串中的第一個字符。

我在正確的軌道上嗎?請注意,這是所有的僞代碼,因爲我還在努力學習C語法

#include <stdio.h> 

int main() { 
    create address to 'a' 
    create address to 'b' 
    make 'a' a string like "abcdefg" 
    make 'b' a string like 'b' 
    call findMatch(a,b); //pass in both to a function 
    return 0; // I know I have to have this at the end 
} 

void findMatch(char a, char b){ 
    Retrieve the pointer to the first character in the 'a' string 
    Increment through 'a' to see if it matches the dereferenced b 
    If 'a' contains 'b' print its in the string as well as the address of the location in 'a' 
} 

example run - findMatch("abcdef","f") gives a print statement that says 'f' is in 'abcdef' and the address location of 'f' 

我看過有建立在C字符串函數庫,但我要處理的指針自己學習。

由於

+0

問題是C *沒有*字符串。我們只有字符數組,並按照慣例在字符串的最後一個重要字符之後放置了一個「\ 0」。 – 5gon12eder 2014-09-30 01:12:22

+0

你基本上不得不相信有這樣的東西作爲一個「串」 - 沒有。內存中可能有字節,你認爲*是一個字符串,* *像字符串一樣對待,但對於系統來說,它們也可能代表一個蕪菁。那麼,什麼是字符串純粹取決於你要跟蹤。而且,由於沒有什麼可以調用「字符串」,因此'char *'指針只是指向RAM中某處的指針。你是否可以認爲它是一個「字符串」,純粹是你如何處理它的問題。 – 2014-09-30 01:12:48

+0

因此,在「abcd」的字符數組中,是否有一種方法可以引用「a」並通過數組增加它?謝謝 – asdf 2014-09-30 01:14:56

回答

2

在C:

  • 指針是一個地址。你幾乎可以互換使用這些術語。
  • 數組變量是指向其引用的數組的第一個元素(即地址)的指針。
  • 一個字符串只是一個字符數組(或非寬字符的wchar)。

當您的代碼包含像的聲明:

char a[] = "ABCDEF"; 

編譯器分配的整個字符陣列加上足夠的存儲器中的適當位置的後\0終止字節(例如,堆疊),並寫入相應的字節。

記住你的變量a現在是第一個字母'A'的地址;因此你可以像指針一樣使用它。例如,與*運營商訪問其值(稱爲提領),並比較其:

*a == 'A' // commonly written as: a[0] == 'A' 

將評估爲true。因此,所有以下評估爲真:

*(a + 1) == 'B' // commonly written as: a[1] == 'B' 
*(a + 2) == 'C' // commonly written as: a[2] == 'C' 
*(a + 3) == 'D' // commonly written as: a[3] == 'D' 
*(a + 4) == 'E' // commonly written as: a[4] == 'E' 
*(a + 5) == 'F' // commonly written as: a[5] == 'F' 
*(a + 6) == '\0' // commonly written as: a[6] == '\0' 

讓我知道是否需要任何額外的說明。

+0

這確實有助於這是我所希望的。謝謝!如果我在main()中聲明'char a [] =「abcd」,我應該想要傳入* a作爲函數中的參數,然後傳入地址,然後可以將其解除引用到我的數組中? – asdf 2014-09-30 01:40:02

+0

如果您想將'a'傳遞給另一個函數,則不應使用星號。只需用'foo(a)'調用函數即可。然後,函數'foo'將被聲明爲'void foo(char * a){// code goes here}'或'void foo(char a []){// code goes here}'這是相同的當然,如果你返回一個值,則替換爲'void')。 – Will 2014-09-30 01:47:16

+0

順便說一句,我真的認爲你應該得到一本適當的書,以深入瞭解基本面。我的推薦:* C編程:現代方法* K. N. King。 – Will 2014-09-30 01:50:47

0

考慮,在C所有的RAM是char一個巨大的陣列。沒有什麼實質性的東西將一個概念實體與另一個概念實體分開。

您可以在RAM中擁有一個字符串作爲字節H o w . n o w . b r o w n . c o w (zero byte),並且緊接着在0x01 0x02 0x03 0x04之後代表我的退休賬戶中的餘額。如果將字符串更新爲「現在如何使用牛」,那麼您將在退休餘額上寫下「牛」字樣,並且我將進入窮人臥室(如果我不在那裏)。 (雖然實際上「牛」可能是一個改進)。

RAM是一個巨大的char數組,而任何類型的指針只是指向該數組的指針。沒有什麼東西將RAM中的某個位置標記爲某種類型,並且,由於可以對指針進行任意算術運算,因此幾乎可以訪問任何內容(在進程地址空間中)或修改任何內容,無論是否有意義所以還是不行。

0

爲了儘可能簡單地把這個地:

char* str1 = "Hello world, goodbye world."; char* str2 = *str1;

您將分配給指針值str2在該位置的char值由str1指向。由於'H'的ASCII碼爲0x48,因此str2指向的位置變爲0x48。因此,如果您解除引用str2,您將嘗試在內存中的位置0x48處讀取一個字節。

str1實際上位於內存中的位置0x48並且可能會工作一次,這是極不可能的,但可能的是,str1實際上位於內存中的位置0x48。但絕不應該依靠那個。

你可能在這裏要做的是char* str2 = str1;。在這種情況下,str2現在指的是str1在分配時所做的相同位置(因此,如果更改str1,但將str2保持不變,則在解除引用str2時可能會出現問題,如果刪除了指向的內存)。但是他們仍然指的是內存中的同一個塊,因此改變str1str2的一些內容將分別推遲str2str1,或者更改指向BOTH的塊的內容,或者因爲內存已移動而導致無效別的地方。這取決於正在完成的操作。

如果你想要一個單獨的副本,你必須複製內存塊。 size_t len = strlen(str1); str2 = new char [len]; memcpy(str2,str1,len);然後,您也必須分別刪除它們。 delete [] str1;不會影響str2,並且delete [] str2;不會影響str1。如果副本被克隆並存儲在單獨的內存塊中,則它們不以任何方式連接。

這個故事的寓意是你並不真正把字符串當作實體來處理,而只是在概念上。你正在處理字符數組,就像處理整數數組或指針數組(技術上是整數數組,只是一種特定類型)。

+0

其實,沒有你會從編譯器得到一個錯誤(或者至少是一個警告),試圖用'char'初始化一個char * ... – 2014-09-30 02:44:40

+0

是的,你是對的。但是,理論上...... – rsethc 2014-09-30 19:48:07