Initializing a C Structure with Pointer to Pointer
I am working on creating a hash table implementation for the assignment. I have defined my hash table as a structure like this:
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 need to initialize a hashtable structure in a method using double pointers like:
void init(hashtable** ht) {
...
}
I wrote 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 compilation 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, the following confuses me: 1. I'm not sure how to create a new structure in the init function when passing a pointer to a pointer. 2. After selecting the structure, how can I change the attributes of the structure element?
source to share
There are 2 errors in the code:
-
int table*
→int *table
- Declare a pointer to an integer -
* ht-> size
(*ht)->size
- > - Import parentheses if you are not sure about operator precedence
source to share
The problem is
->
has higher precedence than *
C as you can see from here
using priority rules *ht->size
translates to * (ht-> size). This should clearly state the reason why you are getting the error. Another way to see this is
*(ht->size)=(*(*ht).size)
Fix it with parentheses like this: (*ht)->size
There hashtable
is another problem in the definition :
int table*;
will not compile. Use int *table;
instead to declare pointer to int
?
source to share
This is a good start, and the others are major problems 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);
}
source to share
Thanks everyone for the quick response. For future reference here, you can quickly update the source code with the 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);
}
source to share