如何优雅地构造在 C 中遍历数组的长参数列表

Posted

技术标签:

【中文标题】如何优雅地构造在 C 中遍历数组的长参数列表【英文标题】:how to elegantly construct long argument lists that iterate through arrays in C 【发布时间】:2014-09-16 11:59:26 【问题描述】:

我有一个接受可变参数的 C 函数,我需要用很长的参数列表调用它,其中所有参数都遍历数组的元素。示例:

myFunction( A[0], B[0], A[1], B[1], A[2], B[2], A[3], B[3], ..... A[N], B[N] );

其中 N 通常为 100-200。

我宁愿不必每次使 N 变大时都手动构造这个调用,并开始思考,有没有一种优雅的方法来做到这一点?

我尝试了类似的方法:

i=0;
myFunction( A[i], B[i++], A[i], B[i++], A[i], B[i++], A[i], B[i++], ..... A[i], B[++] );

但这当然失败了。然而,它更受欢迎的是,每当我使 N 变大时,我可以简单地一遍又一遍地复制同一行,而不必确保每个数组索引都是正确的,这非常乏味。

更改 myFunction() 不是一种选择。

我希望 C 有一种即时构造函数调用的方法,例如:

for( i = 0 ; i <= N ; i++ )

    CONSTRUCT_CALL( myFunction, A[i], B[i] );

这正是我想要的,但这当然不是一个选择。

有什么可能更简单或更优雅的吗?

非常感谢。

【问题讨论】:

五分之四的程序员只是朝自己的头部开枪。 对不起,但我不明白为什么你不能在这种情况下只做 myFunc(type* A, type*B) 然后在内部遍历两个数组。 在同一行有多个i++ 是通过downvote 处罚的罪行;) @Borgleader:只有没有排序限制。喜欢这里。 为什么不能改变函数原型?这部分是生产代码还是家庭作业?并且函数调用中的多重自增一元运算符是模棱两可和愚蠢的。 【参考方案1】:

没有标准的 C 方法可以做到这一点(在运行时合成可变参数调用)。但是……

您可以使用libffi 来处理此类问题(所以我推荐它) 你可以考虑 GCC 特定的Builtins for Constructing Calls 您可以对 arity 有一些固定限制(例如 500),并使用一些(shell、awk、Python、...)脚本生成一些 C 文件,在 500 个案例上执行 switch,其中一个用于每一个元素。 您可以考虑在运行时生成一些 C 代码到 _gen123.c,将其编译成动态可加载插件(例如,在 Linux 上派生一些 gcc -shared -fPIC -Wall -O _gen123.c -o _gen123.so 命令),然后加载该插件(使用 @ 987654323@ 在 Linux 或 Posix 上) 您可以考虑使用一些 just-in-time compilation 库(例如 libjit、llvm、GNU lightning、asmjit、...)

当然,避免在一个呼叫中使用多个i++。避免使用undefined behavior,因为bad things 可能会发生。

【讨论】:

全面,疯狂程度增加+1。【参考方案2】:

您的设计中有一些非常糟糕的地方。

重写您的myFunction,使其需要两个数组(A 和 B),然后使用多个索引。

调用此类函数的简短示例:

int A[100];
int B[100];
int c = myFunction(A, B, 100);

myFunction 的可能实现:

int myFunction(int* A, int* B, int count)

    int result = 0;
    for(int j = 0; j < i; j++)
        result += A[j] + B[j]*2;

    return result;

【讨论】:

但他说:改变myFunction()不是一种选择 是的,没注意到。无论如何,仍然没有其他选择可以正确地做这件事;)也许这里一个好的解决方案是准备myFunction2以更好的方式做同样的事情? 除非有采用va_list 的函数变体,否则没有可用的“更好”(和标准化)方式。真的有人在制作这样的函数接口,真是太可悲了。

以上是关于如何优雅地构造在 C 中遍历数组的长参数列表的主要内容,如果未能解决你的问题,请参考以下文章

C 函数中的变量参数列表 - 如何正确遍历 arg 列表?

遍历构造函数的参数

c语言如何遍历枚举元素

树的遍历

拉链在实践中的表现如何,应该在啥时候使用?

如何从数组列表中提取项目并对其进行计数,以便从元素及其总计数(正确)在 Java 中创建映射?