【问题标题】:C all type parameterC 所有类型参数
【发布时间】:2009-11-02 16:20:30
【问题描述】:

如何编写一个接受 C 中泛型类型参数的函数? (比如一个int、一个char...)

【问题讨论】:

  • 这样不会破坏强类型语言的目的吗?也许您可以尝试将其作为 int 传递,因为 chars 可以说是 int。
  • @RobbR 有支持这种机制的强类型语言。强类型与此无关。静态的编译时类型才是真正的优势。
  • @圣哈辛托:???见en.wikipedia.org/wiki/Perp
  • C 不是一种特别强类型的语言。不过,它的输入是静态的。
  • @Sinan...是的,对不起。你的链接是准确的。这是一种美国主义,意思是“你的问题在于这个”。

标签: c function


【解决方案1】:

我个人会这样做:

1) 发送一个指向 void * 的指针作为第一个参数

2) 发送第二个参数,告诉您 void * 是什么(可能性的枚举)并将参数 1 转换为该参数

这会让你编写带有很多开关的丑陋代码,但如果仔细完成并经过彻底测试,可能会奏效。

类似:

// the enum:
BYTE_VALUE = 1; INT_VALUE = 2, CHAR_VALUE = 3 etc

// the function
int parse(void *arg, enum_type arg_type)
{
    if (arg == NULL) return -1;

    switch(arg_type)
    {
    case BYTE_VALUE:
        byte value = (byte) *arg;
        // do work here
    case INT_VALUE:
     // etc
    }

    return something;
}

编辑:假设您不想要可变参数函数(在我看来这不是您想要的)

【讨论】:

  • 是的,我想要这样的功能。这是一个很好的实现,但我希望看到更简洁的(如果有人的话)。谢谢。
  • 别忘了放一个'break;'在每个案例的末尾。
  • 如果你使用联合而不是做所有的转换会更好
  • 为了对所有神圣事物的热爱,编写宏来为您调用函数,而不是在每次使用时都包含类型枚举。这将使您的代码免受枚举和调用约定中的更改的影响,并且通过执行以下操作使您更难在脚上开枪:double d = 0.5;解析(&d, INT_VALUE);
  • 我想你可能会发现byte value = (byte) *arg;需要是byte value = *((byte *) arg);
【解决方案2】:

有不同的方法,都有各自的缺点。

  • 已经提到:使用 void 指针并相应地转换它。您不能将值作为参数提供,而需要为这些值使用变量:

   myfunc(&7); 

不起作用,而是:

int x = 7;
myfunc(&x);
  • 已经提到:可变参数函数。您必须小心默认转换,并且可能需要转换值。

  • 使用联合作为参数。和void指针一样,需要预置一个联合变量。

  • 我通常更喜欢为不同的类型使用单独的函数。


void myfuncchar (char c);
void myfuncint (int i);

根据问题,将公共部分放入子函数时通常不会有太多代码重复。

【讨论】:

    【解决方案3】:

    您可以考虑使用 printf 方法。它传入一个参数,该参数标识被调用函数的类型。

    printf("%d",  intvalue);
    printf("%f",  floatvalue);
    printf("%s",  stringvalue);
    

    这是一个link,它演示了如何实现变量参数列表。

    【讨论】:

      【解决方案4】:

      我已经有一段时间没有做这样的事情了,所以请检查语法。

      从劳拉的回答出发,使其更简洁:

      // the enum:
      enum types{ int_val, char_val, float_val };
      // the functions
      
      int (*funcArr[3])(void*) = {NULL};
      
      
      int to_do_if_int(void* input)
      {
         return 0;
      }
      
      int to_do_if_char(void* input)
      {
         return 0;
      }
      
      int to_do_if_float(void* input)
      {
         return 0;
      }
      
      void initializer()
       {
         funcArr[int_val] = &to_do_if_int;
         funcArr[char_val] = &to_do_if_char;
         funcArr[float_val] = &to_do_if_float;
       }
      
      int parse(void *arg, enum_type arg_type){    
         if (arg == NULL) return -1;
      
         (*funcArr[arg_type])(arg);
      
         return something;
      }
      

      【讨论】:

      • 这有利于保持你的代码相对干净。当你想为一个新类型做一些新的事情时,你只需编写函数,将类型添加到枚举中,然后将其添加到初始化程序中。 3 个步骤,但您的代码易于维护,因为每种类型都有自己的功能,而不是在 switch 案例中。
      • +1 在考虑代码维护时,这确实比 switch 示例更有效。
      【解决方案5】:

      如果您不想传递指针,则可以传递联合。像结构一样声明联合,但一次只能使用一个成员。例如:

      union foo {
      char c;
      int i;
      }
      
      struct foo f;
      f.c = 'd';
      function (f);
      f.i = 23;
      function(f);
      
      int function(union foo f)
      ...
      

      请记住,您一次只能使用一个字段,如果您将 f.c 设置为某个值,那么 f.i 的值将会以一种可能混乱的方式发生变化。 (我相信这是未定义的行为,但如果编译器除了逐字节替换之外做了任何事情,它将无法编译大量现有代码。)另外,请记住,该语言不提供关于您上次更改的字段的任何线索,因此您可以通过某种方式对其进行跟踪。

      这不是一个非常干净的解决方案,但void * 也不是。你试图颠覆 类型系统,你不会得到一个好的解决方案。

      【讨论】:

      • +1 指出可以使用 (struct+)union 来处理这一切(包括省略的“类型选择”),而无需强制转换为 void*。例如,这种方法在 MAPI API 中被广泛使用(比如快 3 倍!)。
      【解决方案6】:

      您正在寻找的东西称为可变参数函数。以下链接是有关该主题的维基百科文章:

      http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D

      【讨论】:

      • 可变参数函数采用任意数量的参数,而最初的问题是关于采用泛型类型的参数。虽然可变参数函数可以做到这一点,但如果参数数量已知,您可以在没有可变参数函数的情况下解决问题。
      • 即使使用可变参数函数,在使用 va_next() 宏来推进变量参数时,您也需要有关类型的信息。例如 printf()-family 将类型信息嵌入到格式字符串中。
      【解决方案7】:

      使用void* 是通常的方式。例如检查 memcpy 的实现,它就是这样做的——它接受任何类型的参数。您应该知道,如果您想处理“正确”传递的数据(除非您不进行像 memcpy 和类似的真正处理,您需要知道原始类型(即,将其类型转换为数据最初具有的类型)函数),因为传递 void* 并没有说明任何内容——它只是指向某个内存的指针,没有任何关于其内容、长度或解释的信息。因此,您的函数需要自行处理,可能使用不同的参数来说明类型。例如,memcpy 需要一个以字节为单位传递数据长度的参数。

      【讨论】:

        【解决方案8】:

        最好的办法是使用模板。您可以使用 void 指针,但如果操作不正确,可能会导致其他问题。 最好的办法是去HERE 阅读教程并亲自尝试。理解模板的概念应该没有任何问题。

        【讨论】:

        • 主题说C。他的意思是C#吗?如果是这样,哎呀
        • 话题说C,你的答案是C++。
        • 哈哈又是一个减一。我来这里的时间不长,但我开始发现这里有些人对诸如误解问题之类的事情非常敏感。
        • 目标是正确答案在页面上高于错误答案。这是一个不正确的答案,因此应该投反对票。如果您不想再次被否决,可以将其删除。
        猜你喜欢
        • 2014-06-29
        • 2021-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-14
        • 2015-06-14
        相关资源
        最近更新 更多