【问题标题】:union of value and function pointer值和函数指针的联合
【发布时间】:2019-02-04 13:32:48
【问题描述】:

我正在努力使用工会。为什么我无法将函数指针传递到联合所在的位置?任何帮助将不胜感激。

编辑:删除 typedef

#include <stdio.h>

union U {
    int(*fnPtr)(int);
    int i;
};

enum E {
    OPTION_0 = 0,
    OPTION_1 = 1
};

int multiply_by_two (int x) {
    return 2 * x;
}

int f (int x, enum E e, union U u) {
    switch (e) {
        case OPTION_0:
            /* Return the sum */
            return x + u.i;
        case OPTION_1:
            /* Return 2 * x */
            return u.fnPtr (x);
    }
}

int main (void) {
    int a;
    scanf ("%d", &a);
    int b = f (a, OPTION_1, &multiply_by_two);
    printf ("%d\n", b);
    return 0;
}

【问题讨论】:

  • 另外,看看this问题。
  • union U 不是int(*fnPtr)(int)union U 有一个该类型的成员。
  • 抱歉,typedef 是一个错误,是从内存中输入的:/我已经删除了它
  • @Z4ckZ3r0 通常,从不重新输入代码。只需复制并粘贴您正在运行的内容。一个小小的改动就可以在功能代码和非功能代码之间产生很大的不同。
  • 发布的代码,当通过编译器 (gcc) 运行时会导致: gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled2.c" : In function 'main ': :31:29: 错误:'f' int b = f (a, OPTION_1, &multiply_by_two) 的参数 3 的类型不兼容; :17:5:注意:预期的'union U',但参数的类型是'int(*)(int)' int f(int x,enum E e,union U u){:在函数'f'中::26 :1: 警告:控制到达非空函数 [-Wreturn-type] } 编译失败。

标签: c unions


【解决方案1】:

首先,这个定义是无效的:

union U {
    typedef int(*fnPtr)(int);
    int i;
};

typedef 不能包含在 structunion 中。删除 typedef 会给你一个正确的定义:

union U {
    int(*fnPtr)(int);
    int i;
};

第二个问题在这里:

int b = f (a, OPTION_1, &multiply_by_two);

函数f 需要union U,但您传递给它的是int (*)(int)。这些类型不兼容。仅仅因为联合具有该类型的成员并不意味着您可以在使用联合的任何地方使用该类型。您需要创建一个联合,设置适当的字段,然后将其传递给函数。

union U u;
u.fnPtr = multiply_by_two;
int b = f (a, OPTION_1, u);

【讨论】:

  • 只是一个小错字:typedef 在第二个 sn-p 中没有被删除。
  • 我明白了,所以联合不能隐式确定哪个字段有效,必须手动分配。有没有办法隐含地做到这一点?
  • @Z4ckZ3r0 不,struct和union类型与其他类型之间没有隐式转换
  • @Groo 谢谢,我错过了。固定。
【解决方案2】:

在主函数中,试试这个:

int main()
{
  ...
  union U myUnion;
  myUnion.fnPtr = &multiply_by_two;
  int b = f (a, OPTION_1, myUnion);
  ...
}

另外,联合定义不正确,需要删除typedef

【讨论】:

    【解决方案3】:

    只是添加到其他答案:这通常称为变体数据类型,将类型枚举与struct 一起保存在union 中是有意义的,因为您将在所有的反正时间。

    所以我建议将两者都放在struct

    enum var_type
    {
        VAR_INT = 0,
        VAR_FUNC = 1
    };
    
    struct variant
    {
        // contains the type of the stored value
        enum var_type type;
    
        // contains the actual value
        union {
            int(*fnPtr)(int);
            int i;
        };    
    };
    

    然后您可以使用单独的函数来创建每个子类型,以实现更简单的实例化:

    // wrap the int value in the variant struct
    struct variant variant_create_int(int i)
    {
        return (struct variant){ .type = VAR_INT, .i = i };
    }
    
    // wrap the functino pointer in the variant struct
    struct variant variant_create_func(int(*fnPtr)(int))
    {
        return (struct variant){ .type = VAR_FUNC, .fnPtr = fnPtr };
    }
    

    意思是你的main 会做这样的事情:

    // create variant of type 'VAR_FUNC'
    struct variant var = variant_create_func(&multiply_by_two);
    

    然后将 var 结构向前传递。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-29
      • 1970-01-01
      • 2013-11-05
      • 1970-01-01
      • 2011-12-13
      • 2012-02-11
      相关资源
      最近更新 更多