代码之家  ›  专栏  ›  技术社区  ›  Hatefiend

C-检查结构数组的索引是否未初始化

  •  0
  • Hatefiend  · 技术社区  · 8 年前

    我正在用C语言制作HashMap,但在检测节点是否已初始化时遇到了问题。

    static struct Node
    {
        void *key, *value;
        struct Node *next;
    };
    
    
    struct Node **table;
    int capacity = 4;
    table = malloc(capacity * sizeof(struct Node));
    
    // At this point I should have a pointer to an empty Node array of size 4.
    
    if (table[0] != NULL)
    {
        // This passes
    }
    

    我不知道我能在这里做什么。我读过很多其他类似性质的帖子,但他们的解决方案对我来说毫无意义。

    enter image description here

    2 回复  |  直到 8 年前
        1
  •  1
  •   R Sahu    8 年前

    malloc 不会初始化分配的内存。你可以使用 calloc 零初始化内存。

    // Not sizeof(struct Node)
    // table = calloc(capacity, sizeof(struct Node));
    table = calloc(capacity, sizeof(*table));
    

    在此之后,使用以下内容是有意义的:

    if (table[0] != NULL)
    {
       ...
    }
    
        2
  •  -1
  •   Richard Chambers    8 年前

    我建议您考虑类似HashMapCollection类型的东西,它是用一组函数创建的,用于处理所需的各种内存操作。

    因此,您可能有如下代码。我没有测试过它,也没有编译过它,但它是一个起点。

    这个 FreeHashMapCollection() HashMapCollection 在释放管理数据结构之前释放它所包含的内容。这可能不是你想做的,所以你需要考虑。

    下面的想法是为 哈希映射集合 struct和的数组或列表 HashMapNode 结构会立即跟随管理数据,因此单个 free()

    typedef struct _TAGHashMapNode {
        void *key, *value;
        struct _TAGHashMapNode  *next;
    } HashMapNode;
    
    typedef struct {
        int  iCapacity;   // max number of items
        int  iSize;       // current number of items
        HashMapNode *table;  // pointer to the HashMapNode table
    } HashMapCollection;
    

    然后有一个函数来分配 哈希映射集合 正确初始化特定容量。

    HashMapCollection *AllocateHashMapCollection (int iCapacity)
    {
        HashMapCollection *p = malloc (sizeof(HashMapCollection) + iCapacity * sizeof(HashMapNode));
    
        if (p) {
            p->table = (HashMapNode *)(p + 1);
            p->iCapacity = iCapacity;
            p->iSize = 0;
            memset (p->table, 0, sizeof(HashMapNode) * iCapacity);
        }
        return p;
    }
    
    HashMapCollection *ReallocHashMapCollection (HashMapCollection *p, int iNewCapacity)
    {
        HashMapCollection *pNew = realloc (p, sizeof(HashMapCollection) + sizeof(HashMapNode) * iNewCapacity);
    
        if (pNew) {
            pNew->table = (HashMapNode *)(pNew + 1);
            if (p == NULL) {
              // if p is not NULL then pNew will have a copy of that.
              // if p is NULL then this is basically a malloc() so initialize pNew data.
              pNew->iCapacity = pNew->iSize = 0;
            }
            if (iNewCapacity > pNew->iCapacity) {
                // added more memory so need to zero out that memory.
                memset (pNew->table + iCapacity, 0, sizeof(HashMapNode) * (iNewCapacity - pNew->iCapacity));
            }
            pNew->iCapacity = iNewCapacity;    // set our new current capacity
            p = pNew;   // lets return our new memory allocated.
        }
        return p;    // return either old pointer if realloc() failed or new pointer
    }
    
    void FreeHashMapCollection (HashMapCollection *p)
    {
        // go through the list of HashMapNode items and free up each pair then
        // free up the HashMapCollection itself.
    
        for (iIndex = 0; iIndex < p->iCapacity; iIndex++) {
            if (p->table[iIndex].key) free (p->table[iIndex].key);
            if (p->table[iIndex].value) free (p->table[iIndex].value);
            // WARNING ***
            // if these next pointers are actually pointers inside the array of HashMapNode items
            // then you would not do this free as it is unnecessary.
            // this free is only necessary if next points to some memory area
            // other than the HashMapNode table of HashMapCollection.
            if (p->table[iIndex].next) free (p->table[iIndex].next);
            // even though we are going to free this, init to NULL
            p->table[iIndex].key = NULL;
            p->table[iIndex].value = NULL;
            p->table[iIndex].next = NULL;
        }
        free (p);    // free up the memory of the HashMapCollection
    }