我正在尝试研究C,而我正在使用char *和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 word []和char *基本上是一回事。唯一的区别是char字[1024]在堆栈中的固定长度为1024,但堆中的tmp只占用了必要的空间(strlen(word)+1)。
因此我不明白为什么我必须在堆中复制字符串才能调用此函数。为什么会这样? char * tmp = strdup(“something”)和char word [1024] =“something”之间是否存在一些更基本的区别?
答案 0 :(得分:6)
你提到你需要char **
并且存在问题:对于数组,word
和&word
意味着相同的事情 - 数组内容的实际位置。它使用指针时的工作原因是因为“指针”存储位于不同的位置,而指向指向同一个数组。您不需要strdup
,只需创建一个指针:
char* tmp = word;
HashSetLookup(stopList, &tmp);
答案 1 :(得分:1)
没有HashSetLookup的文档很难说。
但是它期望const void *作为它的第二个参数,所以你应该传递tmp,而不是& tmp,因为tmp已经是一个指针。
我根本不认为需要char **。
此外,您可能对HashSetLookup()返回的内容感兴趣。
答案 2 :(得分:0)
你必须在第一个例子中遗漏了一些东西,因为根本没有使用“word”。
无论如何,在大多数环境中,当你编写'char * s =“Hello World”'时,它会在代码段上创建,无法修改。代码段意味着它是可执行代码的一部分,不能修改但只能读取。当你尝试编写它时,你会遇到一个段错误。
但是'char []'会在数据段上创建,因此可以毫无问题地进行修改。
答案 3 :(得分:0)
答案 4 :(得分:0)
由于你提到char**
我认为问题在于试图写的函数到第二个参数指向的位置,即你写的时候:
HashSetLookup( stopList, &word );
它会尝试为word
分配一个地址(这就是为什么它需要它的地址。),它会用指针覆盖缓冲区。
以下愚蠢的片段证明了这一点(请记住,数组的地址仍然是其第一个元素的地址):
#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;
}