我可以从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;