【问题标题】:Modifying signature of a function pointer修改函数指针的签名
【发布时间】:2011-05-19 17:36:51
【问题描述】:

我在这里遇到了一个小问题,我有这个函数指针:

typedef void* (* funcPointer)(const void *in, int ilen, void *out, int *olen)

还有这个功能

void* foo1(const void *in, int ilen, void *out, int *olen)
{
   if(CONST_VALUE_1 > iLen)
      //do something
   else
      //do something else
   return whatever;
}

代码中的某处

// ...
funcPointer fpointer = foo1;
if(someArgument > SOME_OTHER_CONSTANT)
   // where foo2 is the same as foo1 except that it uses CONST_VALUE_2
   fpointer = foo2; 
bar( someVariable, anotherVariable, fpointer);
// ...

如您所见,此函数的主体中有一个CONST_VALUE_X。我希望能够删除常量并改用第五个参数。由于我无法修改签名,所以我想知道是否有什么事情要做或使用 每个 可能的常量值复制粘贴函数...

谢谢

【问题讨论】:

  • 您是否可以控制传递给回调函数的任何值?
  • 你能把它包起来吗?为什么不创建一个采用第 5 个参数的基本函数,然后从尊重您签名的函数中传递 CONST_VALUE_X 来调用它?
  • @TurqMage 不,我对栏功能没有任何控制权
  • 也许这个 C 中的柯里化实现可以提供一些线索:stackoverflow.com/questions/1023261/…
  • 听起来你可以修改foo1,但不能修改它的签名(因为它必须通过bar的函数指针调用,你不能改变bar)。那是对的吗?如果是这样,那么您可能应该定义一个带有额外参数的函数foo,然后让foo1CONST_VALUE_1 调用它,foo2CONST_VALUE_2 调用它。如果没有 C 所缺乏的某种形式的闭包或部分函数应用程序,这几乎是你能做到的最好的事情。

标签: c function pointers


【解决方案1】:

如果你不能修改函数签名,那么正如你所说,你不会有第五个参数!

我看到三个选项:

  1. 我猜你可以把它硬塞到其他void * 参数之一中(例如定义一个包含in 的原始值和“常量”值的结构,然后将其作为@ 987654323@)。

  2. 在调用函数之前设置一个全局变量。 这是个坏主意。

  3. 您可以将此函数编写为宏,以避免复制和粘贴维护的噩梦。 这是个坏主意。

【讨论】:

  • 是的,这就是我的想法,但我希望有一个更好、更清洁的解决方案。
  • @Francis:我不确定你期待什么样的解决方案!最好和最干净的解决方案是修改签名。如果你不能这样做,你就会得到像上面这样的混乱解决方案。
  • 选项#1 是最好的选择。 C 语言没有你想要的高级功能,所以你必须自己发明它。无论如何,让你做你想做的事情的语言可能在“幕后”做#1,它比预处理器宏或全局变量要干净得多。
【解决方案2】:

您可以将常量替换为调用者可以临时更改的内容(如全局变量)。

例如:

int oldLenghtLimit = LengthLimit;
... call the function ...
LengthLimit = oldLengthLimit;

并且,在函数中:

void* foo1(const void *in, int ilen, void *out, int *olen)
{
  if(LengthLimit > iLen)
    //do something
  else
    //do something else
  return whatever;
}

【讨论】:

  • 当然,这只有在我们知道调用者遵循该约定时才有效。
  • 并非如此,因为调用后恢复了原始值,旧代码仍然可以工作(假设LengthLimit被初始化为CONST_VALUE_1)。
  • 我的意思是,如果你将五个函数指针分发到你无法控制的某个地方,那么它们就必须遵循这个约定,否则它将无法工作。
【解决方案3】:

你想要的是一个闭包,而C语言没有明确支持闭包。您可以通过修改 API 以携带函数指针和参数指针而不只是函数指针来实现相同的目的。然后你只需要函数的版本:一个使用显式调用者提供的参数,另一个使用来自携带的参数指针的值。

【讨论】:

    猜你喜欢
    • 2018-02-05
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 2016-11-07
    • 2013-11-13
    • 2016-02-22
    • 2015-06-21
    • 1970-01-01
    相关资源
    最近更新 更多