在C中创建可动态扩展的内存数组

时间:2015-04-12 20:36:04

标签: c arrays pointers

在我的下面的代码中,我试图创建一个动态可扩展的内存数组。

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

#define BLOCKSIZE 5

int hash_table_length = 0;
int *currentblock = NULL;
int size_left;
int *hash_table = NULL;
int *start = NULL;

int *create_hash_table() {

    int *tmp;

    if (currentblock == NULL || size_left == 0) {

        if (currentblock == NULL) {
            currentblock = (int *) malloc( BLOCKSIZE * sizeof(int));
            start = currentblock;
            size_left = BLOCKSIZE;
        } else {
            currentblock = (int *) malloc( BLOCKSIZE * sizeof(int));
            size_left = BLOCKSIZE;
        }
    }
    tmp = currentblock++;
    size_left -= 1;

    return tmp;

}

void build() {

    int hash;

    int i = 0;
    for (i = 0; i < 20; i++) {
        hash = i + 3;

        if (hash_table_length == 0) {

            hash_table = create_hash_table();
            hash_table_length++;
        } else {
            hash_table = create_hash_table();
            hash_table_length++;
        }

        hash_table = &hash;
        printf("hash value is %d\n", *hash_table);

    }
}

int main() {

    build();

// How do I reach the start of the hash table again?
// the below start does not give me the first value
    printf("Hash table first value is %d\n", *start);
    return 0;
}

我的问题是希望遍历hash_table中存储的值。我无法访问hash_table的第一个元素/地址。我希望打印出哈希表中存储的所有值。怎么办呢?

1 个答案:

答案 0 :(得分:1)

在您的代码中,hash值永远不会存储在哈希表中(currentblock内)。在create_hash_table()函数内部,您为新块分配内存,但从不在此块中存储值。因此,如果您尝试取消引用这些int*位置中的任何一个,则可能会获得垃圾值(可能为0)。 当您取消引用start指针时,这正是main()函数内部正在发生的事情。它实际上指向哈希表的开始,并且由于该位置未初始化,因此它给出了0的输出。 要在哈希表中实际存储值,请在build()

中更改以下内容
hash_table = &hash;

为:

*hash_table = hash; // Store value of 'hash' inside the memory location pointed to by hash table(which happens to be 'current_block' inside build())

现在,如果您尝试运行代码,它将输出3。

关于如何遍历整个哈希表的问题的第二部分:使用此代码无法完成。这是因为malloc的整数块之间没有联系。 malloc()调用可以从堆中分配任何可用内存块。因此,在当前形式中,您已经断开了无法遍历的位置块。

您可以使用realloc来增加当前块的大小,而不是malloc。 realloc为较大的块分配内存,并将以前的数据复制到此新块。这基本上允许您使用start遍历整个哈希表。

您可以这样做:

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

#define BLOCKSIZE 5

int hash_table_length = 0;
int *currentblock = NULL;
int size_left;
int *hash_table = NULL;
int *start = NULL;

int *create_hash_table() {

    int *tmp;

    if (currentblock == NULL || size_left == 0) {

        if (currentblock == NULL) {
            currentblock = (int *) malloc(BLOCKSIZE * sizeof(int));
            start = currentblock;
            size_left = BLOCKSIZE;
        } else {
            /* Call realloc() to allocate new memory block of size (hash_table_length+BLOCKSIZE) and copy previous data*/
            currentblock = ((int *) realloc(start,(hash_table_length + BLOCKSIZE) * sizeof(int))) + hash_table_length;
            size_left = BLOCKSIZE;
        }
    }
    tmp = currentblock++;
    size_left -= 1;
    return tmp;

}

void build() {

    int hash;

    int i = 0;
    for (i = 0; i < 20; i++) {
        hash = i + 3;

        if (hash_table_length == 0) {

            hash_table = create_hash_table();
            hash_table_length++;
        } else {
            hash_table = create_hash_table();
            hash_table_length++;
        }
        /* Store value of hash inside the hash_table */
        *hash_table = hash;
        printf("hash value is %d\n", *hash_table);

    }
}

int main() {
    int i;
    build();
    printf("Hash table first value is %d\n", *start);

    /* Traverse the hash table */
    for(i = 0; i < hash_table_length; ++i)
        printf("hash_table[%d] = %d\n",i,*start++);
    return 0;
}