【问题标题】:multi-type operation function in CC中的多类型运算函数
【发布时间】:2013-12-18 07:59:53
【问题描述】:

我正在编写一个函数,它只是将两个值相加,

但是这些值的C类型是在参数中指定的,

可以是 int、unsigned int、char、unsigned char、float ...

我搜索了一个解决方案来做到这一点,而无需编写大量 C 代码来处理所有不同的混合情况。

要清楚代码是:

void addition(unsigned char type_data_1_uc, void *value_data_1_ptr, 
              unsigned char type_data_2_uc, void *value_data_2_ptr, 
          unsigned char type_result_uc, void *value_result_ptr)
{

    /* types :
       0 : TYPE_BIT
       1 : TYPE_CHAR 
       2 : TYPE_UNSIGNED_CHAR
       3 : TYPE_INT
       4 : TYPE_UNSIGNED_INT
       5 : TYPE_SHORT_INT
       6 : TYPE_UNSIGNED_SHORT_INT
       7 : TYPE_LONG
       8 : TYPE_UNSIGNED_LONG
       9 : TYPE_FLOAT */

    /* INT + INT = INT */
    if ((type_data_1_uc == 3)
     && (type_data_2_uc == 3)
     && (type_result_uc == 3))
    {
     *((int *) value_result_ptr) = *((int *) value_data_1_ptr) + *((int *) value_data_2_ptr);
    }

    /* FLOAT + FLOAT = FLOAT */
    if ((type_data_1_uc == 9)
     && (type_data_2_uc == 9)
     && (type_result_uc == 9))
    {
     *((float *) value_result_ptr) = *((int *) value_data_1_ptr) + *((int *) value_data_2_ptr);
    }

    /* UNSIGNED CHAR + INT = INT */
    if ((type_data_1_uc == 2)
     && (type_data_2_uc == 3)
     && (type_result_uc == 3))
    {
     *((int *) value_result_ptr) = *((unsigned char *) value_data_1_ptr) + *((int *) value_data_2_ptr);
    }

    /* ......... */

}


int main(int argc, char **argv)
{

    int data_1;
    int data_2;
    int result;

    data_1 = 26;
    data_2 = 32;


    addition(3, &data_1, 3, &data_2, 3, &result);

    printf("result = %d\n", result);

    return 0;   

}

我想过使用联合结构,但它并没有解决问题,因为联合也需要静态转换:

/* UNION DATA */
union data_union 
{
    char tab_c[4];
    unsigned char tab_uc[4];
    int i;
    unsigned int ui;
    short int si;
    unsigned short int usi;
    long l;
    unsigned long ul;
    float f;
};


void addition(unsigned char type_data_1_uc, union data_union *value_data_1_ptr, 
              unsigned char type_data_2_uc, union data_union *value_data_2_ptr, 
          unsigned char type_result_uc, union data_union *value_result_ptr)
{

    /* types :
       0 : TYPE_BIT
       1 : TYPE_CHAR 
       2 : TYPE_UNSIGNED_CHAR
       3 : TYPE_INT
       4 : TYPE_UNSIGNED_INT
       5 : TYPE_SHORT_INT
       6 : TYPE_UNSIGNED_SHORT_INT
       7 : TYPE_LONG
       8 : TYPE_UNSIGNED_LONG
       9 : TYPE_FLOAT */


        /* INT + INT = INT */
        if ((type_data_1_uc == 3)
         && (type_data_2_uc == 3)
         && (type_result_uc == 3))
        {
         (*value_result_ptr).i = (*value_data_1_ptr).i + (*value_data_2_ptr).i;
        }

        /* FLOAT + FLOAT = FLOAT */
        if ((type_data_1_uc == 9)
         && (type_data_2_uc == 9)
         && (type_result_uc == 9))
        {
         (*value_result_ptr).f = (*value_data_1_ptr).f + (*value_data_2_ptr).f;
        }

        /* UNSIGNED CHAR + INT = INT */
        if ((type_data_1_uc == 2)
         && (type_data_2_uc == 3)
         && (type_result_uc == 3))
        {
         (*value_result_ptr).i = (*value_data_1_ptr).uc + (*value_data_2_ptr).i;
        }

}


int main(int argc, char **argv)
{

    static union data_union data_1_union;
    static union data_union data_2_union;
    static union data_union result_union;

    memset(&data_1_union, 0, sizeof(union data_union));
    memset(&data_2_union, 0, sizeof(union data_union));

    data_1_union.i = 26;
    data_2_union.i = 32;


    addition(3, &data_1_union, 3, &data_2_union, 3, &result_union);

    printf("result_union.i = %d\n", result_union.i);

    return 0;   

}

有什么办法解决这个问题吗?

【问题讨论】:

  • 用例是什么?为什么不简单地编写一个函数add(long long, long long) 并以某种方式处理浮动案例?
  • 这很奇怪,这是什么目的?这是现实世界的问题还是只是学术问题?
  • 我觉得你应该分析一下你的需求。
  • 是的,这是一个现实世界的问题,我的值最初是在数据库中,我得到它们并与多种类型结合起来,之后我必须在它们之间进行一些计算

标签: c


【解决方案1】:

如果没有一些“痛苦”,您将无法做到这一点,因为 C 是静态类型语言。编译器需要知道变量的类型才能生成正确的指令。大多数 CPU:s 都有不同的指令来添加 8 位整数、32 位整数、浮点数等。

也就是说,你当然可以改进界面:我会使用可变参数来制作原型:

typedef enum {
  TYPE_BIT = 0,
  TYPE_CHAR,
  TYPE_UNSIGNED_CHAR,
  TYPE_INT,
  TYPE_UNSIGNED_INT,
  TYPE_SHORT_INT,
  TYPE_UNSIGNED_SHORT_INT,
  TYPE_LONG,
  TYPE_UNSIGNED_LONG,
  TYPE_FLOAT,
} Type;

void addition(Type type, void *result, ...);

这需要用四个参数调用,后两个应该具有type 参数所指示的类型。结果存储在result,它应该是指向与参数相同类型的指针。

不确定如何表示单个位值,可能是unsigned char,但这有点毫无意义:单个位不是一种可以在 C 中进行算术运算的类型,因此您最终只能进行加法运算有更多位,然后将其中一些屏蔽掉。在大多数机器上,您也不能拥有指向内存中单个位的指针。

【讨论】:

    【解决方案2】:

    解决这个问题的惯用 C 方法是使用宏来尽可能地消除代码重复。不幸的是,其余的必须手动完成。例如:

    enum typecode {
      TC_INT = 3,
      TC_FLOAT = 9,
      /* ... */
    };
    
    void addition(enum typecode type_data_1_uc, void *value_data_1_ptr, 
                  enum typecode type_data_2_uc, void *value_data_2_ptr, 
                  enum typecode type_result_uc, void *value_result_ptr)
    {
    #define DO_ADD(tc1, tc2, tcret, type1, type2, typeret) do {        \
      if (type_data_1_uc == tc1 && type_data_2_uc == tc2               \
          && type_result_uc == tcret) {                                \
        *(typeret *)value_result_ptr =                                 \
           *(type1 *)(value_data_1_ptr) + *(type2 *)(value_data_2_ptr) \
        return;                                                        \
      } while (0)
    
      /* INT + INT = INT */
      DO_ADD(TC_INT, TC_INT, TC_INT, int, int, int);
      /* FLOAT + FLOAT = FLOAT */
      DO_ADD(TC_FLOAT, TC_FLOAT, TC_FLOAT, float, float, float);
      /* UCHAR + INT = INT */
      DO_ADD(TC_UCHAR, TC_INT, TC_INT, unsigned char, int, int);
      /* ... */
    
    #undef DO_ADD
    
      /* none matched: abort() or set an error code, as appropriate */
    }
    

    【讨论】:

    • 很好,这段代码可以工作,但是它需要一个 DO_ADD 混合操作。
    • @user3114142 抱歉,我不明白您的评论。混合操作是什么意思?第三次调用 UCHAR + INT = INT 应该涵盖混合参数类型的情况,如果这就是您所指的。
    猜你喜欢
    • 2016-04-16
    • 2011-03-05
    • 2016-09-21
    • 2015-06-03
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2014-07-18
    • 1970-01-01
    相关资源
    最近更新 更多