I have a node and I am defining its global pointer variable as below:
typedef struct node
{
char* word;
struct node* next;
} node;
node* HashTable =
Counting the stars.
FOO * foo_ptr = malloc (sizeof (FOO) * n_foos);
// ^ ^
// | |
// one star to the left of `=` one star to the right of `=`
The rule of thumb: the number of stars must be the same at either side of the assignment. Why?
sizeof(FOO) sizeof(FOO) sizeof(FOO)
_____________ _____________ ______________
/ \/ \/ \
_____________ _____________ ______________
[_____FOO_____][_____FOO_____][______FOO_____]
^
|
FOO* foo_ptr; // a FOO* points to a FOO
// pointer arithmetic works by incrementing the address\
// by sizeof(FOO)
// and so on
Other examples of good code:
FOO ** foo_ptr = malloc (sizeof (FOO*) * n_foos); // same number of stars
FOO *** foo_ptr = malloc (sizeof (FOO**) * n_foos); // still same
Bad code:
FOO ** foo_ptr = malloc (sizeof (FOO) * n_foos); // numbers don't match
FOO * foo_ptr = malloc (sizeof (FOO*) * n_foos); // numbers don't match
Your line
HashTable = malloc(sizeof(node*) * numOfElements);
(after substituting the type of HashTable
which is node*
) falls squarely into the bad code bin, so try to fix that.
If you want an array of nodes:
HashTable = malloc(sizeof(node) * numOfElements);
If you want an array of pouners to nodes, you can have that too. This is not really recommended, because space savings are small, performance degradation will probably be substantial, and the code is less elegant. But you can have it:
node** HashTable = malloc(sizeof(node*) * numOfElements); // count! the! stars!
Congratulations! You now have an array of numOfElements
uninitialized pointers. Now you need to initialize them to some value, typically NULL:
for (i = 0; i < numOfElements; ++i) HashTable[i] = NULL;
And you need to allocate a new node
each time you want to put a value to the table:
if (HashTable[hashValue] == NULL)
{
HashTable[hashValue] = malloc(sizeof(node));
if (HashTable[hashValue] == NULL)
{
panic ("Out of memory!");
}
HashTable[hashValue]->word = ...
HashTable[hashValue]->next = ...
}
else
{
// collision etc
}
While we're at it, please note these moments which are tangential to the main question: how to properly check for NULL, how to check the return value of malloc
, and how to use an array index instead of mutating a global pointer variable back and forth. (If you want to use pointer arithmetic, have a local pointer variable in putInHashTable
).
(Of course if you don't use n_foos, or use calloc, you need to make mental adjustments to the number of stars).