You have a slight flaw in your logic. In C, when you declare an array in block scope, the compiler allocates space for that array on the stack.
Example:
Code:
void function(void) {
int newdock[8] = {0,0,0,0,0,0,0,0}; // all 8 of these ints will be on the stack
}
You can verify this by checking the results of this program:
Code:
#include <stdio.h>
typedef int Dock[8];
int main(void) {
int i = 0;
Dock dock1 = {0,0,0,0,0,0,0,0};
int *dock2 = calloc(8, sizeof(int));
printf("%-9s = %d\n", "&i", &i);
printf("%-9s = %d\n", "&dock1", &dock1);
printf("%-9s = %d\n", "&dock1[0]", &dock1[0]);
printf("%-9s = %d\n", "&dock2", &dock2);
printf("%-9s = %d\n", "&dock2[0]", &dock2[0]);
free(dock2);
return 0;
}
It should print something similar to this:
Code:
&i = 2293612 Clearly this must be on the stack
&dock1 = 2293568
&dock1[0] = 2293568 The first element of the array is on the stack
&dock2 = 2293564 The int* is on the stack
&dock2[0] = 4007088 The first element of the int* 'array' is on the heap
Your hash table stores void pointers. That is, it doesn't make a copy of whatever the pointer is pointing to and store THAT in the array, it just stores a copy of the pointer. If you try to declare an array on the stack:
Code:
Dock newdock = {0,0,0,0,0,0,0,0};
newdock[ship] = newdock[ship] + 1;
HashReplace(docks, p->name, newdock);
you cannot store that in your hash table. You would be storing a pointer to an array allocated on the stack, and that memory is going to disappear after the function returns.
Instead, you could make your dock an int pointer. That way you can heap allocate the memory using malloc (or calloc, which will zero it for you). Storing a pointer to heap allocated memory in your hash table is perfectly valid, you just have to member to free it when you're done with it (that may require a modification to your hash table).
This shouldn't change the way you use the dock at all since you can use an int pointer as if it were an array anyway. Make sure to do proper bounds checking (which you would need to do with an array anyway), and you should be all set.
Now, with all that being said, I don't see any problem with you using a struct. You can heap allocate the struct just as easily, plus if you ever need to add anything to the dock in the future, it won't require too much effort, just add an additional field to the struct. I think this would actually make your code seem cleaner, and it won't hurt efficiency. I would much rather see this:
Code:
dock->ship[n] // The nth ship in the dock
than this:
Code:
dock[n] // The nth dock??
But that's just a matter of personal preference.