3

I'm working on creating a hash table implementation for an assignment. I've defined my hashtable as struct as follows:

typedef struct hashtable {
  int size;
  int entries;
  int table*;   // pointer to table. Each entry will point to linked list 
                // of key-value nodes 
} hashtable;

I have to initialize the hashtable struct in a method using double pointers, e.g.:

void init(hashtable** ht) {
...
}

I've written a basic implementation below:

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

typedef struct hashtable {
  int size;
  int entries;
  int table*;   // pointer to table. Each entry will point to linked list 
                // of key-value nodes 
} hashtable;

void init(hashtable**);

void init(hashtable** ht) {
    *ht = (hashtable *) malloc( sizeof(hashtable) );
    *ht->size = 3;
}

int main(){

  hashtable *t = NULL;
  init(&t);

  printf("t.size: %i", t->size);
}

However, I keep getting the following compile error:

ll.c:19:8: error: member reference base type 'hashtable *' (aka 'struct hashtable *') is not a
      structure or union
    *ht->size = 3;
     ~~^ ~~~~
1 error generated.

So I'm confused by the following: 1. I'm not sure how to create a new struct in the init function when being passed a pointer to pointer. 2. After allocating the struct, how do I modify the struct member attributes?

2
  • 5
    this *ht->size = 3; --> (*ht)->size = 3; Commented Jul 12, 2017 at 22:46
  • int table*;??? Commented Jul 12, 2017 at 22:54

5 Answers 5

2

This is just a operator precedence problem.

The compiler processes -> before the *. Therefore, it tries to access the size member of struct hashtable ** which is not possible.

The code compiles if you exchange *ht->size with (*ht)->size.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks that fixed the issue.
2

You have 2 errors in your code :

  1. int table* --> int *table - Declare pointer to integer

  2. *ht->size --> (*ht)->size - Imp to put brackets when you are not sure of operator precedence

Comments

1

That's a good start, and others have addresses the primary issues in your code. However, I would suggest a minor tweak:

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

typedef struct hashtable {
  int size;
  int entries;
  int table*;   // pointer to table. Each entry will point to linked list 
                // of key-value nodes 
} hashtable;


// note: freeing the hashtable is a caller responsibility!
hashtable *new_hashtable() {
    hashtable *ht = malloc( sizeof(hashtable) );
    ht->size = 3; // since ht is only a single pointer, no need for (*ht)->foo 

    return ht;
}

int main(){

  hashtable *ht = new_hashtable();

  printf("ht.size: %i", ht->size);

  free(ht);
}

2 Comments

appreciate the feedback on returning the pointer. I'm constrained here by my assignment specifications.
Oh I see. Well just keep this in mind for the future. This way is safer, because you're never meant to assign NULL. You just get the pointer directly from the function, without a chance to forget to call init.
1

The problem is that

-> has higher precedence than * in C as you can see from here

using precedence rules *ht->size translates to *(ht->size). That should make clear the reason why you get the error. Another way to see it is

*(ht->size)=(*(*ht).size)

Fix this using parenthesis as follows: (*ht)->size

There is another issue in the definition of hashtable: int table*; won't compile. Use int *table; instead to declare a pointer to int?

Comments

0

Thanks all for the quick response. For future reference, here's a quick update of the original code with solutions:

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

typedef struct hashtable {
  int size;     // size of hash table
  int entries;  // number of slots allocated in table
  int *table;   /* pointer to table. Each entry will point to linked list
                  of key-value nodes */
} hashtable;

void init(hashtable**);

void init(hashtable** ht) {
    *ht = (hashtable *) malloc( sizeof(hashtable) );
    (*ht)->entries = 0;
    (*ht)->size = 3; //replace this with better init size, ideally a prime number
    (*ht)->table = malloc( (*ht)->size  * sizeof(int));
}

int main(){

  hashtable *t = NULL;
  init(&t);
  t->table[2] = 3;

  printf("t.size: %i \n", t->size);
  printf("t.arr:[2] %i \n", t->table[2]);
  free(t);
}

1 Comment

You'll probably want to use calloc

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.