【问题标题】:C: Different type declaration by casting void pointer in a functionC:通过在函数中转换 void 指针来声明不同的类型
【发布时间】:2013-02-17 03:04:39
【问题描述】:

以下insertSNode 函数插入itemreturns 更新的指针。在insertSnode 函数中,来自不同struct 的每个数据都会被相应地取消引用。

问题: 我在 (LINE 1)、(LINE 2)、(LINE 3)、(LINE 4) 上收到编译器错误,并显示以下错误消息:

“成员引用基类型 'void' 不是结构或联合。”

问题:

如何消除编译器错误?如果我不能,或者,我们是否有更好的解决方案来编写与这种情况相同的函数?假设struct 类型太多(即Type_A、Type_B 等),用不同的类型声明创建不同的函数是极其低效的。

*pListTypeA = (Type_A *) insertSnode(*pListTypeA, pPreTypeA, pTypeAItem, TYPEA);
*pListTypeB = (Type_B *) insertSnode(*pListTypeB, pPreTypeB, pTypeBItem, TYPEB);
*pListTypeC = (Type_C *) insertSnode(*pListTypeC, pPreTypeC, pTypeCItem, TYPEC);
// more assignments

insertSnode定义:

void* insertSnode(void* pList, void* pPre, char* item, const int type) {
    void *pNew;

    if (TYPEA == type) {
        pList = (Type_A*) pList;
        pPre =  (Type_A*) pPre;
        pNew =  (Type_A*) pNew;
    } else if (TYPEB == type) {
        pList = (Type_B*) pList;
        pPre =  (Type_B*) pPre;
        pNew =  (Type_B*) pNew;
    } else (TYPEC == type) {
        pList = (Type_C*) pList;
        pPre =  (Type_C*) pPre;
        pNew =  (Type_C*) pNew;
    }
    if (!(pNew = malloc(sizeof(*pList)))) {
        printf(ERR_NOT_ENOUGH_MEMORY);
        exit(EXIT_NOT_ENOUGH_MEMORY);
    }
    pNew->name = item;    // compiler error: (LINE 1)
    if (pPre == NULL) {
        pNew->link = pList;    // compiler error: (LINE 2)
        pList = pNew;
    } else {
        pNew->link = pPre->link;    // compiler error: (LINE 3)
        pPre->link = pNew;    // compiler error: (LINE 4)
    }
    return pList;
}

注意:

仅供参考:我能够在没有用于类型声明的 if 语句和只有一种类型(例如 Type_A)的情况下运行此代码。所以,我们都知道除了类型声明之外没有任何外部问题。

【问题讨论】:

  • 坦率地说,我相信每种类型都有一个专用函数会更好——即使它更冗长。您正在采用的方法将使您的insertSNode 函数随着时间的推移变得越来越大并且越来越难以维护。也许您应该重新考虑拥有这么多列表?

标签: c casting struct void-pointers


【解决方案1】:

这里的问题是下面一行

pList = (TYPE_A*) pList;

仍然分配给void* 指针,因此强制转换没有用,其余代码的行为就好像它没有发生一样。

我不知道一个干净的方法来整齐地解决这个问题我很抱歉。我本来打算建议一个中间的struct,但因为你想直接修改实例,所以这行不通。

如果这是C++,那么泛型就是答案..

要使您当前的想法发挥作用,您需要为每种类型创建不同的变量并转换为这些变量,或者在每次要使用变量时进行转换。

或者按照 Michael Pryor 的建议尝试将类型统一为一种。

否则,您可以尝试使用宏 - 请参阅下面的示例以了解上述代码的一行。

#define OPERATEONTYPE(Type,TypeEnum)\
if(type == TypeEnum) {\
    ((Type*)pNew)->name = item;\
}


void* insertSnode(void* pList, void* pPre, char* item, const int type) {
         OPERATEONTYPE(Type_A,TYPEA)
    else OPERATEONTYPE(Type_B,TYPEB)
    else ....
}

#undef OPERATEONTYPE //should only be used/usable within that function anyway

【讨论】:

  • 我应该为不同的类型创建不同的类型名称吗?我的意思是,我应该声明Type_A* paList; Type_B* pbList;(……等等……)吗?
  • 这是失败原因的正确答案。至于如何修复它,也许您可​​以只使用 ONE 类型,并在您的类型中添加一个变量以区分 A/B/C 等。
  • @JaneBerman 我打算这样做,但如果你这样做,你也需要对其余代码执行此操作,并且到目前为止只创建许多函数会更简洁跨度>
  • @KarthikT 感谢您的回答/评论。我只想在这里澄清一件事。在C,一旦你声明了类型,你就不能改变它的类型了吗? void *pNew;pNew = (Type_A*) pNew; 不适合这种感觉?
  • C99 允许,C89 不允许:stackoverflow.com/questions/8474100/…
【解决方案2】:

如果每个“结构类型”都有一些共同的值(名称、下一个、上一个等),那么也许您想使用联合?将公共部分存储在通用结构中,然后使用联合来存储非公共部分。

注意@KarthikT 的回答是正确的,这些确实是语法错误,因为 pNew 始终是一个 void 类型,并且没有与之关联的“结构”,所以 pNew->name 是一个无意义的构造。

【讨论】:

  • 我喜欢union 的想法。我会在我的代码上试试!非常感谢!
【解决方案3】:

正如 Karthik 所说,您必须在 c++ 中使用泛型。
在 c 中,有一个解决方案。 删除insertSnode() 中的第一个if...else if...else 块。
如下使用。

void* insertSnode(void* pList, void* pPre, char* item, const int type) {
void *pNew;
 if (!(pNew = malloc(sizeof(*pList)))) {
    printf(ERR_NOT_ENOUGH_MEMORY);
    exit(EXIT_NOT_ENOUGH_MEMORY);
}
if (TYPEA == type) {
   if(pPre==NULL){
   (Type_A*)pNew->name=item;
   (Type_A*)pNew->link=plist;
   (Type_A*)pList=pNew;
 }else{
    (Type_A*)pNew->link=(Type_A*)pPre->link;
     (Type_A*)pPre->link;
  }
} else if (TYPEB == type) {
    if(pPre==NULL){
   (Type_B*)pNew->name=item;
   (Type_B*)pNew->link=plist;
   (Type_B*)pList=pNew;
 }else{
    (Type_B*)pNew->link=(Type_B*)pPre->link;
     (Type_B*)pPre->link;
  }
} else if(TYPEC == type) {
   if(pPre==NULL){
   (Type_C*)pNew->name=item;
   (Type_C*)pNew->link=plist;
   (Type_C*)pList=pNew;
 }else{
    (Type_C*)pNew->link=(Type_c*)pPre->link;
     (Type_C*)pPre->link;
  }
}


return pList;
}

【讨论】:

  • 这是正确的......但是如果我有很多类型,这段代码看起来不太干净......如果我有 26 种类型怎么办??
  • -1 用于复制粘贴,更好的建议是将其做成宏
猜你喜欢
  • 2021-04-08
  • 1970-01-01
  • 2021-09-20
  • 2011-07-31
  • 2015-02-14
  • 2012-11-21
  • 2020-08-12
  • 2018-05-25
相关资源
最近更新 更多