3

在 C 中,有没有一种方法可以调用存储在某个数组中的参数的函数?我是 C 新手,我什至不确定这是否正确,但例如:

void f0(int a) { ... };
void f1(int a, int b) { ... };
void f2(int a, int b, int c) { ... };

int array[5][2][?] = [
    [&f0, [5]],
    [&f1, [-23, 5]],
    [&f2, [0, 1, 2]],
    [&f2, [1235, 111, 4234]],
    [&f0, [22]]
];

int i;
for (i = 0; i < 5; i++) {
    APPLY?(array[i][0], array[i][1])
}

PS:当数组的项目长度不同时,我应该使用什么样的结构?

在 Python 中,这将是:

def f0(a): ...
def f1(a, b): ...
def f2(a, b, c): ...

array = [
    (f0, (5,)),
    (f1, (-23, 5)),
    (f2, (0, 1, 2)),
    (f2, (1235, 111, 4234)),
    (f0, (22,))
]

for f, args in array:
    apply(f, args)
4

5 回答 5

2

不是真的,不。

在 C 中执行此操作的更好方法是将您的函数定义为都具有相同的签名,例如:

void f0(int size, int elements[])

然后将适当大小的数组传递给您的函数。

// this is a function pointer
void (*x)(int, int[]); 
...
// set x to point at f0
x = f0;
// call x (ie: f0) with 1 element from position 5 of array
x(1, &(array[5]));
于 2009-10-08T16:16:05.743 回答
2

C中可能有可变的arity函数,但机制笨拙,有一定的限制,即必须至少有一个固定参数,并且您需要能够从固定参数或可变参数本身判断哪里变量列表的结尾是。

一个更典型的解决方案,一个发挥 C 的优势而不是它的弱点,就像这个例子一样。(用函数指针更新。)

#include <stdio.h>

void f1(int, int *);
void f2(int, int *);

struct BoxOfInts {
    void (*f)(int,int *);
    int howMany;
    int theNumbers[4];
} intMachine[] = {
    {f1, 1,  { 5,  }},
    {f2, 2,  { -23, 5  }},
    {f1, 3,  { 0, 1, 2  }},
    {f2, 3,  { 1235, 111, 4234  }},
    {f1, 1,  { 22,  }},
    { 0 }
};

void dispatch(void)
{
    for(struct BoxOfInts *p = intMachine; p->f; ++p)
        (*p->f)(p->howMany, p->theNumbers);
}

void f1(int howMany, int *p)
{
    while (howMany-- > 0) {
        int t = *p++;
        printf("f1 %d %d\n", howMany, t);
    }
}

void f2(int howMany, int *p)
{
    while (howMany-- > 0) {
        int t = *p++;
        printf("f2 %d %d\n", howMany, t);
    }
}

int main()
{
  dispatch();
  return 0;
}
于 2009-10-08T16:22:15.073 回答
0

我想也许你只是想要:

array[i][0](array[i][1]);

在 C 中从指针调用函数只需要函数调用运算符,即括号。

可能有用的链接: http ://boredzo.org/pointers/

于 2009-10-08T16:22:34.967 回答
0

c 没有内置的列表或列表理解的概念,您必须在数组上设置一个显式循环,并且必须自己支持列表的长度。

是的,这比 python 方式更冗长,但那是因为 python 正在为您处理细节。

相当适合处理概念“列表”的数据结构:

  • 动态数组(可能包含在 astruct中,让您将元信息(如当前长度和分配长度)保存在同一个地方)
  • 链表

如果您选择基于阵列的解决方案,您将需要

  1. 跟踪当前长度并将其传递给处理函数
  2. 使用哨兵标记数据的结尾(这可能意味着使用更大的数据类型以允许您指定不能出现在数据中的哨兵)

链表可以逐个节点处理,因为它有一个自然结束。

于 2009-10-08T16:52:08.883 回答
0
#include <stdio.h> 

void f0(int a              ){ printf("f0(%i)\n",      a    ); }
void f1(int a, int b       ){ printf("f1(%i,%i)\n",   a,b  ); }
void f2(int a, int b, int c){ printf("f2(%i,%i,%i)\n",a,b,c); }

typedef void (*f_arg1)(int);
typedef void (*f_arg2)(int,int);
typedef void (*f_arg3)(int,int,int);

struct fn_call {
  f_arg1 fn;
  int arg_num;
  int *args;
} array[] = {  { (f_arg1)f0, 1, (int[]){5}               },
               { (f_arg1)f1, 2, (int[]){-23, 5}          },
               { (f_arg1)f2, 3, (int[]){0, 1, 2}         },
               { (f_arg1)f2, 3, (int[]){1235, 111, 4234} },
               { (f_arg1)f0, 1, (int[]){22}              }   };

void apply( struct fn_call *call ){
  switch( call->arg_num ){
  case 1: ((f_arg1)call->fn)( call->args[0] );                  break;
  case 2: ((f_arg2)call->fn)( call->args[0], call->args[1] );   break;
  case 3: ((f_arg3)call->fn)( call->args[0], call->args[1], call->args[2] );
  }
}

int main(){
  for(unsigned i=0; i<sizeof(array); i++)  apply( &array[i] );
}

结果:

f0(5)
f1(-23,5)
f2(0,1,2)
f2(1235,111,4234)
f0(22)
于 2009-10-08T17:19:59.077 回答