moe asal
moe asal

Reputation: 582

When address is changed values gets altered

I am trying to implement a hash table in c. So i initialize my table like this:

int size = 4;
float filled_values = 0;


struct block{
    short int empty;
    int value;
};


void initialize(struct block **table){
    int i;
    free(*table);
    *table = malloc(size * sizeof(struct block));
    for(i = 0; i < size; i++) (*table)[i].empty = 0;
    return;
}


int main(){
    struct block *table;
    table = NULL;
    initialize(&table);
}

everything works fine with insertions too.

void insert_utility(int value, struct block **table){
    int index = hash(value);
    int i = index;
    for(;; i = (i + 1) % size){
        if ((*table)[i].empty == 0){
            (*table)[i].value = value;
            (*table)[i].empty = 1;
            return;
        }
    }
}

void insert(int value, struct block **table){
    insert_utility(value, table);
    int i;
    filled_values++;
    if (filled_values / (float)size >= 0.5) double_table(table);
    return;
}

However when the table gets half full, I double the tables size to ensure reliablity.

void double_table(struct block **table){
    int i;
    int old_size = size;
    size *= 2;
    struct block **table_2;
    *table_2 = malloc(size * sizeof(struct block) * 2);

    for(i = 0; i < size; i++) (*table_2)[i].empty = 0;

    for(i = 0; i < old_size; i++){
        if ((*table)[i].empty == 1){
            insert_utility((*table)[i].value, table_2);
        }
    }
    free(*table);
    table = table_2;

}

I debugged the code to know where the error gets a block with the value empty of neither 0 or 1.

It turns out that after I assign table = table_2; and check the values at table everything is fine.

Whereas after double_table exits in the insert function, I recheck the values of empty and value at each block, I get different results with non-sense pointer-like big values. How could've the values been altered in that way?

Upvotes: 0

Views: 33

Answers (1)

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

You need to understand that you are working in your function on a new table, your table_2, and when you are done, you must pass it back to the caller, the **table parameter. Applying my comments gives the following function:

void double_table(struct block **table)
{
    int i;
    int old_size = size;
    struct block *table_2;  // this is the new table that you are working on. Just one * is enough

    size *= 2;
    table_2 = malloc(size * sizeof(struct block) * 2);

    for(i = 0; i < size; i++) table_2[i].empty = 0;

    for(i = 0; i < old_size; i++){
        if ((*table)[i].empty == 1){
            insert_utility((*table)[i].value, &table_2);
        }
    }
    free(*table);      // this is correct, now do that too in the following statement
    *table = table_2;  // dereference the caller's parameter so you assign to his variable.
}

Upvotes: 1

Related Questions