I have a type defined like this:
struct DynTab_s {
int object_count;
//other fields
void *data;
};
typedef struct DynTab_s *Dyntab_t; //note that type I use is pointer to struct
I have a storage utility that I can user to store and retrieve them. I’ve chosen to support int, double and pointer type. I have a function to retrieve the int and double values by key:
int MyHashtableGet(MyHashtable_t Hashtable, void *Key, void *Value)
{
void *Row = NULL;
int RetValue = -1;
MakeRow(Hashtable, Key, NULL, &Row);
if (!MyStoreSelect(Hashtable->TableId, Row))
{
switch (Hashtable->ValueType)
{
case MY_HASHTABLE_TYPE_INT:
*(int *)Value = *(int *)((char *)Row + Hashtable->KeySize);
break;
case MY_HASHTABLE_TYPE_POINTER:
//after row below I can see the DynTab_t in the item when I cast it
Value = *(void **)*(int **)((char *)Row + Hashtable->KeySize);
break;
}
}
MyFree(Row);
return RetValue;
}
that work for int. But not for pointer when I try to get Dyntab_t. This works if I use function
void *MyHashtableGetPointer(MyHashtable_t Hashtable, void *Key)
{
void *Row = NULL;
void *RetValue = NULL;
MakeRow(Hashtable, Key, NULL, &Row);
if (!MyStoreSelect(Hashtable->TableId, Row))
RetValue = *(void **)*(int **)((char *)Row + Hashtable->KeySize);
MyFree(Row);
return RetValue;
}
when I call it with:
int Key = 1;
DynTab_t MyTab;
MyTab = (DynTab_t)MyHashtableGetPointer(MyHashtable, &Key);
The question is can I at all use this MyHashtableGet to get DynTab_t item or does second parameter have to be void ** type? If yes, can you please provide the exact syntax to call and to MyHashtableGet in case of MY_HASHTABLE_TYPE_POINTER.
Thanks & BR -Matti
The only difference (if you’re storing the pointers like you store the
intvalues) would be that when retrieving anint, you’d pass the address of anintvariable; and when retrieving a pointer, you’d pass the address of a pointer variable. Avoid *can hold the address of anything (except functions sometimes) — including other pointers. So the last parameter is fine asvoid *, as long as you handle it appropriately elsewhere.I’m not sure what you’re doing in your function, though. If you store the pointers the same way as the
ints in your data structure, so that at the same level of indirection you’d have anintfor the integer type and avoid *for the pointer type, then why are they dereferenced to different levels?In the above, it seems that
((char *)Row + Hashtable->KeySize)gets you the pointer to whatever value you’ve stored, though of the wrong pointer type. Then the(int *)casts to a pointer of your data’s type (intin this case), which you then dereference and assign to whatValuepoints to.But here, you cast to
int **, dereference, cast tovoid **, then dereference again, and assign toValueinstead of whatValuepoints at? Isn’t that one too many dereferences? Shouldn’t you assign to the target ofValuerather thanValue? And why do you need to cast toint **at all? I think it should be more like this:Then, when calling to get an int:
…and when calling to get a pointer:
Edit:
This assumes one of two things, though: That the the variable you passed the address of in
Valueisvoid *, or that the variable you passed the address of is of a type that is internally represented the same way asvoid *(often true, but not guaranteed). If you want to rely on the pointer type being converted on assignment (in case their representations differ), you could implement yourMyHashtableGetPointer()function as a wrapper forMyHashtableGet():