C 关于结构内存分配机制的一些困惑?

C 关于结构内存分配机制的一些困惑?,c,linux,dynamic-memory-allocation,C,Linux,Dynamic Memory Allocation,在我的项目中,我遇到了C程序 如下所示,htmp是一个结构指针。我们首先为它分配一个内存。但是为什么我们要再次为它的元素word分配内存呢 如果必须为结构的每个元素分配内存,为什么不为它的其他元素分配内存,id和next #定义HASHREC bitewisehash typedef结构hashrec{ 字符*字; 长id; 结构hashrec*next; }哈什雷克; /*从Hugh Williams转到前面的散列和散列函数,http://www.seg.rmit.edu.au/code/zw

在我的项目中,我遇到了C程序

  • 如下所示,
    htmp
    是一个结构指针。我们首先为它分配一个内存。但是为什么我们要再次为它的元素
    word
    分配内存呢
  • 如果必须为结构的每个元素分配内存,为什么不为它的其他元素分配内存,
    id
    next
  • #定义HASHREC bitewisehash
    typedef结构hashrec{
    字符*字;
    长id;
    结构hashrec*next;
    }哈什雷克;
    /*从Hugh Williams转到前面的散列和散列函数,http://www.seg.rmit.edu.au/code/zwh-ipl/ */
    /*简单按位散列函数*/
    无符号整数位哈希(char*word、int-tsize、无符号整数种子){
    字符c;
    无符号整数h;
    h=种子;
    对于(;(c=*word)!='\0';word++)h^=((h>2));
    返回((无符号整数)((h&0x7fffffff)%tsize));
    }
    /*在哈希表中插入字符串,检查应不存在的重复项*/
    void hashinsert(HASHREC**ht,char*w,long-long-id){
    HASHREC*htmp,*hprv;
    无符号int-hval=HASHFN(w,TSIZE,SEED);
    对于(hprv=NULL,htmp=ht[hval];htmp!=NULL&&scmp(htmp->word,w)!=0;hprv=htmp,htmp=htmp->next);
    if(htmp==NULL){
    htmp=(HASHREC*)malloc(sizeof(HASHREC));#为htmp分配内存
    htmp->word=(char*)malloc(strlen(w)+1);#为什么要再次分配内存?
    strcpy(htmp->word,w);#
    htmp->id=id;#为什么不为htmp->id分配内存?
    htmp->next=NULL;#为什么不为htmp->next分配内存?
    如果(hprv==NULL)ht[hval]=htmp;
    else hprv->next=htmp;
    }
    else fprintf(标准,“错误,重复条目位于:%s.\n”,htmp->word);
    返回;
    }
    
    当您为结构分配内存时,只为成员
    word
    分配了足够的内存来容纳指针,该指针还必须指向您可以分配的有效内存


    如果不指向有效内存,它的值是不确定的,尝试用不确定的值取消引用此类指针是未定义的行为。

    为结构分配内存时,只为成员
    word
    分配足够的内存来保存指针,该指针还必须指向可以分配的有效内存


    如果不指向有效内存,它的值是不确定的,尝试用不确定的值取消引用此类指针是未定义的行为。

    您需要在脑海中区分两件事(1)我要存储的东西在什么内存中?;(2)哪个变量(指针)保存了它存储的地址,这样我就可以再次找到它

    首先声明指向
    struct hashrec
    的两个指针:

    HASHREC *htmp, *hprv;
    
    指针只不过是一个变量,它将指向其他对象的地址作为其值。当您第一次声明这两个指针时,它们是未初始化的,没有地址。然后,您以一种相当尴尬的方式,在
    for
    循环声明中初始化两个指针,例如
    hprv=NULL,htmp=ht[hval]
    和之后的
    hprv=htmp,htmp=htmp->next
    ,所以现在可能两个指针都在某个地方持有地址和点

    在循环之后(使用空的主体),测试
    if(htmp==NULL)
    ,这意味着
    htmp
    不指向地址(如果您发现感兴趣的哈希索引为空,则可能是这种情况)

    然后,为了为一个
    HASHREC
    (例如
    struct HASHREC
    )提供存储,您需要分配存储空间,以便有一块内存来存储您想要存储的东西。因此,分配一个块来保存一个结构。(见:)

    现在,看看您分配了哪些内存:

    typedef struct hashrec {
        char    *word;
        long long id;
        struct hashrec *next;
    } HASHREC;
    
    您已经为包含(1)一个
    char*字的结构分配了存储空间(指向char-8字节(x86上为4字节)的指针);(2) a
    长id(两个都是8字节)和(3)一个指针,用于保存序列中下一个
    HASHREC
    的地址

    毫无疑问,
    id
    可以保存一个
    long
    值,但是
    word
    next
    呢?它们都是指针。指针代表什么?他们指的东西可以找到的地址。在哪里可以找到
    word
    ?您想要的东西当前由
    w
    指向,但不能保证
    w
    将继续保留您想要的单词,因此您将制作一份副本并将其作为
    HASHREC
    的一部分存储。你看:

    htmp->word = malloc(strlen(w) + 1);    /* useless cast removed */
    
    现在
    malloc
    返回什么?它将地址返回到新内存块的开头,
    strlen(w)+1
    字节长。由于指针持有其他内容的值作为其值,
    htmp->word
    现在将新内存块开头的地址作为其值存储。因此
    htmp->word
    “指向”新的内存块,您可以使用
    htmp->word
    作为引用来引用该内存块

    接下来发生的事情很重要:

        strcpy(htmp->word, w);    # 
        htmp->id = id;            # why not allocate memory for htmp->id ?
        htmp->next = NULL;        # why nor allocate memory for htmp->next?
    
    strcpy(htmp->word,w)
    w
    复制到新的内存块中<代码>htmp->id=id
    id
    的值分配给
    htmp->id
    并且不需要分配,因为分配时:

    htmp = malloc(sizeof(HASHREC));  /* useless cast removed */
    
    为(1)
    char*
    指针分配存储空间,(2)为
    长id分配存储空间和(3)一个
    struct hashrec*
    指针——您已经为
    long
    分配了一个
    htmp->id
    指针,因此
    id
    可以将
    id
    的值存储在
    long
    的内存中

    htmp->next = NULL;        # why nor allocate memory for htmp->next?
    
    您试图存储的内容是什么,需要为
    htmp->next
    重新分配?(提示:当前无任何内容)它将指向下一个
    struct hashrec
    。目前它被初始化为
    N
    
    htmp->next = NULL;        # why nor allocate memory for htmp->next?
    
    {
    word = Elephant
    id = 1245
    }