我可以从C中的函数中获取指向结构的指针作为参数吗?
我有一个定义如下的类型:我可以从C中的函数中获取指向结构的指针作为参数吗?,c,pointers,void-pointers,C,Pointers,Void Pointers,我有一个定义如下的类型: 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 case MY_HASHTABLE_TYPE_POINTER: *(void **)Value = *(void **
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
case MY_HASHTABLE_TYPE_POINTER:
*(void **)Value = *(void **)((char *)Row + Hashtable->KeySize);
break;
我有一个存储实用程序,可以让用户存储和检索它们。我选择支持int、double和指针类型。我有一个通过键检索int和double值的函数:
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;
}
这对int有效,但在我尝试获取Dyntab\u t时对指针无效。如果我使用函数,这是有效的
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;
}
当我称之为:
int Key = 1;
DynTab_t MyTab;
MyTab = (DynTab_t)MyHashtableGetPointer(MyHashtable, &Key);
问题是我是否可以使用这个MyHashtableGet来获取DynTab\u t项,或者第二个参数必须是void**type?如果是,请提供在MY_HASHTABLE_TYPE_指针的情况下调用MyHashtableGet和MyHashtableGet的确切语法
谢谢&BR-Matti这取决于你想怎么做。您可以使用引用(仅在C++中)或指针(C和C++)来执行此操作: 您不需要指向指针的指针,除非您希望返回或更改指针而不是值 调用上述示例:
myStruct s;
changeTheParamRef(s);
changeTheParamPtr(&s);
myStruct *p;
allocStruct(&p);
changeTheParamRef(*p);
changeTheParamPtr(p);
问题是我是否可以使用这个MyHashtableGet来获取DynTab\u t项,或者第二个参数必须是void**type
唯一的区别(如果像存储int
值那样存储指针)是在检索int
时,传递int
变量的地址;在检索指针时,传递指针变量的地址。void*
可以保存任何东西的地址(有时函数除外)——包括其他指针。因此,最后一个参数可以作为void*
,只要您在其他地方适当地处理它
不过,我不确定你在做什么。如果在数据结构中以与int
s相同的方式存储指针,那么在相同的间接级别上,整数类型将有int
,指针类型将有void*
,那么为什么它们会被解引用到不同的级别
case MY_HASHTABLE_TYPE_INT:
*(int *)Value = *(int *)((char *)Row + Hashtable->KeySize);
break;
在上面的例子中,((char*)Row+Hashtable->KeySize)
似乎将指针指向存储的任何值,尽管指针类型错误。然后(int*)
将其转换为数据类型的指针(本例中为int
),然后取消引用并指定给值所指向的对象
case MY_HASHTABLE_TYPE_POINTER:
Value = *(void **)*(int **)((char *)Row + Hashtable->KeySize);
break;
但在这里,您将强制转换为int**
,取消引用,强制转换为void**
,然后再次取消引用,并指定给Value
而不是Value
指向的对象?这不是太多的疏远吗?您不应该将Value
而不是Value
分配给目标吗?为什么您需要强制转换为int**
?我认为应该是这样的:
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
case MY_HASHTABLE_TYPE_POINTER:
*(void **)Value = *(void **)((char *)Row + Hashtable->KeySize);
break;
然后,调用以获取int时:
...
int Val;
MyHashtableGet(Table, Key, &Val);
…调用以获取指针时:
...
void *Val;
MyHashtableGet(Table, Key, &Val);
编辑:
但是,这假设了两件事之一:在值中传递地址的变量是void*
,或者传递地址的变量是一种内部表示方式与void*
相同的类型(通常为真,但不保证)。如果希望依赖于在赋值时转换的指针类型(如果它们的表示不同),可以将MyHashtableGetPointer()
函数实现为MyHashtableGet()
的包装器:
谢谢,但这不是我问题的答案。我想要的是使用1个函数,即MyHashtableGet,从MyHashtable获取所有值。这就是我使用void*值的原因。另外,从一行中获取值比在您的回答中要复杂一些:((void**)*(int**)((char*)行+哈希表->键大小);谢谢迪米特里!我得考虑一下你的回答。我不想承认,但当这些指针超出了最基本的范围时,我对它们非常熟悉。我明天测试。再次感谢。如果您知道指针将始终是Dyntab\u t
(struct Dyntab\u s*
),那么您可以将*(void**)Value=
更改为*(Dyntab\u*)Value=
,这也会考虑void*
和struct Dyntab\u*
的内部表示之间的差异(如果有)。不,我不知道类型。我更喜欢C#程序员,我只是厌倦了没有哈希表/哈希表。所以我试着让它尽可能通用。不管怎样,我现在开始测试你的解决方案!非常感谢dimitri!在函数MyHashtableGet中,就像你说的那样,我的哈希表类型指针:*(void**)Value=*(void**)(char*)Row+Hashtable->KeySize);在调用函数时使用参数void*Value调用它,然后我必须将其转换为Tab2=*(Dyntab\u t*)Value;