2010-07-04 155 views
4

我正在學習C語言,並且正在使用char *和char數組運行。我正在使用庫中的通用哈希集容器(我不想詳細描述)。該庫中包括功能char [1024] vs char *

void *HashSetLookup(hashset *h, const void *elemAddr); 

,我不得不使用的哈希集合搜索,看是否該元素已經存在那裏(散列和比較功能是HashSet的結構的一部分)。在這種情況下,我使用散列集來存儲指向C字符串的指針,或者更具體地說(char * *)。我的問題是,下面的代碼給出了一個分段錯誤:

char word[1024]; 
    /* Some code that writes to the word buffer */ 
    HashSetLookup(stopList, &word); 

而這個代碼工作正常(如預期):

char word[1024]; 
    /* The same code as before that writes to the word buffer */ 
    char* tmp = strdup(word); 
    HashSetLookup(stopList, &tmp); 
    free(tmp); 

我以爲字符字[]與char *基本一致事情。唯一的區別是字符[1024]在堆棧中的固定長度爲1024,但堆中的tmp只佔用足夠的空間(strlen(word)+1)。

因此我不明白爲什麼我必須在堆中創建一個字符串副本才能調用此函數。爲什麼會發生? char * tmp = strdup(「something」)和char word [1024] =「something」之間有一些更基本的區別嗎?

+1

顯示在第一個示例中寫入字的代碼。 – jergason 2010-07-04 19:39:28

+0

在第一個示例中的函數調用之前,我沒有看到正在聲明/使用的變量「tmp」。 – MAK 2010-07-04 19:43:13

+0

MAK,對不起,這是一個錯誤。我現在修好了。 – Siggi 2010-07-04 19:44:34

回答

5

:對一個數組,word&word意味着同樣的事情 - 數組內容的實際位置。當您使用指針它工作的原因是因爲「指針」是存儲在不同的位置,而它同一個數組。您不需要strdup,您只需創建一個指針:

char* tmp = word; 
HashSetLookup(stopList, &tmp); 
+0

這很好。謝謝。 – Siggi 2010-07-04 20:20:49

+0

很好用。這是數組和指針之間的細微差別之一。 – casablanca 2010-07-04 20:23:41

+0

-1因爲答案顯然是錯誤的。 它確實* *做一個根本的區別,如果你通過TMP或TMP。自己嘗試一下,你會看到其他的東西出現。不過你可以使用&tmp [0]。 – Eiko 2010-07-04 20:32:48

0

你必須在第一個例子中遺漏了一些東西,因爲根本沒有使用「單詞」。

無論如何,在大多數環境中,當你編寫'char * s ='Hello World''時,它會在代碼段中創建並且無法修改。代碼段意味着它是可執行代碼的一部分,它不能被修改,只能被讀取。當你嘗試寫下它時,你會遇到seg故障。

但是'char []'被創建在數據段上,所以它可以被修改而沒有任何問題。

+0

他在第一個例子的評論中說,有一些遺漏的代碼寫在單詞上。 – jergason 2010-07-04 19:40:00

+0

你是對的。在第一個代碼應該已經HashSetLookup(STOPLIST,和字),不是HashSetLookup(STOPLIST,&tmp); 我有固定的,現在,謝謝。 – Siggi 2010-07-04 19:42:05

1

很難說沒有HashSetLookup的文檔。

但它期望一個const void *作爲它的第二個參數,所以你應該通過tmp,而不是tmp,因爲tmp已經是一個指針了。

我根本沒有看到char **需要。

此外,您可能會對HashSetLookup()返回的內容感興趣。

+0

謝謝您的回答。 其實我需要存儲的char **,因爲HashSet中會無論無效指針指向複製到固定的內存大小塊。這不是字符串很好地工作,因爲它們是不同大小的。因此,所有的HashSet的功能將需要採取的char **,因爲我只是想店內指向字符串存儲在堆中。 你是對的,我很感興趣,無論HashSetLookup()返回,但由於它墜毀在這一點上我沒有理會包括它的代碼。 – Siggi 2010-07-04 20:03:16

+0

你的簽名和你傳遞的價值觀並不代表這一點現在它正在工作,這很可能是由於另一個bug。 – Eiko 2010-07-04 20:33:48

0

既然你提到char**我認爲這個問題是與函數試圖由第二個參數,即指向的位置,當你寫:

HashSetLookup(stopList, &word); 

它去,並試圖分配一個地址word(這就是爲什麼它需要它的地址),它用指針覆蓋緩衝區。

這是由以下愚蠢的片段展示了(記住,數組的地址仍然是它的第一個元素的地址):你提到你需要一個char **還有就是問題所在

#include <stdio.h> 
#include <stdlib.h> 

void func(void* boo) 
{ 
     char** ptr = (char**)boo; 
     printf("func: got %p\n", boo); 
     *ptr = "bad func"; 
} 

int main(int argc, char* argv[]) 
{ 
     char buf[128], *p; 
     func(&buf); /* buf got overwritten */ 
     printf("array: %s\n", buf); 
     p = malloc(128); 
     func(&p); /* p got new value */ 
     printf("malloc: %s\n", p); 
     return 0; 
} 
+0

我首先想到了類似的東西。但是如果你看看HashSetLookup的原型,你會發現第二個參數是一個指向const的指針。第二,這只是一個查找功能,它不應該寫任何東西。 – Siggi 2010-07-04 20:11:39