簡體   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