如何优雅地构造在 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 中遍历数组的长参数列表的主要内容,如果未能解决你的问题,请参考以下文章