繁体   English   中英

我可以从C函数获取指向结构的指针作为参数吗?

[英]Can I get a pointer to a struct as a parameter from a function in C?

我有一个这样定义的类型:

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

我有一个存储实用程序,可以供用户存储和检索它们。 我选择支持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_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_t项,还是第二个参数必须为void **类型? 如果是,请提供确切的语法,以在MY_HASHTABLE_TYPE_POINTER的情况下调用和MyHashtableGet。

谢谢&BR-马蒂

问题是我可以完全使用此MyHashtableGet来获取DynTab_t项,还是第二个参数必须为void **类型?

唯一的区别(如果像存储int值一样存储指针)将是,在检索int ,您将传递int变量的地址; 在检索指针时,您将传递一个指针变量的地址。 void *可以保存任何内容(有时不包括函数)的地址-包括其他指针。 因此,只要您在其他位置进行适当处理,最后一个参数就可以使用void *

不过,我不确定您在功能中正在做什么。 如果在数据结构中以与int相同的方式存储指针,以便在相同的间接访问级别上,对于整数类型,您将拥有一个int ;对于指针类型,您将拥有一个void * ,那么为什么将它们取消引用到不同的水平?

    case MY_HASHTABLE_TYPE_INT: 
        *(int *)Value = *(int *)((char *)Row + Hashtable->KeySize);
        break;

在上面的代码中, ((char *)Row + Hashtable->KeySize)似乎使指针指向已存储的任何值,尽管指针类型错误。 然后(int *)强制转换为数据类型的指针(在本例中为int ),然后将其取消引用并分配给Value指向的指针。

    case MY_HASHTABLE_TYPE_POINTER:
        Value = *(void **)*(int **)((char *)Row + Hashtable->KeySize);
    break;

但是在这里,您将其强制转换为int ** ,解除引用,强制转换为void ** ,然后再次解除引用,然后分配给Value而不是Value指向什么? 那不是太多的取消引用吗? 你不应该分配到的目标Value ,而不是Value 为何根本需要将其转换为int ** 我认为应该更像这样:

    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);

编辑:这假定以下两件事之一:您通过Value的地址传递的变量为void * ,或者您通过其地址的变量为内部表示的类型与void * (通常为真,但不能保证)。 如果您要依靠在赋值时转换的指针类型(以防它们的表示形式不同),可以将MyHashtableGetPointer()函数实现为MyHashtableGet()的包装器:

void *MyHashtableGetPointer(MyHashtable_t Hashtable, void *Key)
{
  void *res = NULL;
  MyHashtableGet(Hashtable, Key, &res);
  return res;
}

这实际上取决于您要如何做。 您可以使用引用(仅在C ++中)或指针(C和C ++)来实现:

void changeTheParamRef(struct myStruct &s)
{
    myStruct other;
    s = other; // or
    s.something = other.something;
}

void changeTheParamPtr(struct myStruct *s)
{
    myStruct other;
    *s = other; // or
    s->something = other.something;
}

void allocStruct(struct myStruct **s)
{
    *s = malloc(sizeof(myStruct));
}

除非您想返回或更改指针而不是值,否则不需要指向该指针的指针。

调用以上示例:

myStruct s;
changeTheParamRef(s);
changeTheParamPtr(&s);

myStruct *p;
allocStruct(&p);
changeTheParamRef(*p);
changeTheParamPtr(p);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM