如何解决从函数中的 void * 参数返回数组
foo(void* ret_val,int mode,int num_params,...)
可变参数函数 foo()
的一般用途可能涉及返回不同的数据类型以及可以具有各种数据类型的任意数量的输入参数,但我无法找到返回数组的方法。
如何返回数组?
函数定义是第一个参数根据foo()
调用的函数返回任意类型,mode
是操作模式,num_params
是额外输入的数量参数,可以为零。 switch
中有一个 foo()
语句,它依赖于 mode
,可以调用一个或多个函数,并且可以返回任意类型的值。
举一个简单的例子,假设我有以下 3 个由 foo()
调用的函数:
void bar1(int i,int,j) {
// Do some calculations but return nothing.
}
int bar2() {
// Do some calculations and return a value.
}
int* bar(3) {
// Do some calculations with an array and return it.
}
然后在 foo()
中我可以有以下代码:
foo(void* ret_val,...) {
va_list args;
va_start(args,num_params);
switch (mode) {
case 1: {
int a = va_arg(args,int);
int b = va_arg(args,int);
bar1(a,b);
}
break;
case 2: {
int val = bar1();
*(int*)ret_val = val;
}
break;
case 3: {
int* p = new int[10];
p = bar3();
// Add a loop to test out that the array has been read from bar3(),which works.
*(int*)ret_val = *p; // <== This is where the problem is.
}
break;
}
va_end(args);
}
然后在主程序中,我可以通过以下方式调用 foo()
:
int x;
foo(&x,1,2,10,20); // Call bar1()
foo(&x,0); // Call bar2()
printf("%d\n",x);
int xd[10]; // Declare and initialize xd.
for (int i = 0; i < 10; i++) {
xd[i] = 0;
}
foo(xd,3,0) // Call bar3()
for (int i = 0; i < 10; i++) {
printf("%d %d\n",i,xd[i]);
}
我调用了 bar1()
和 bar2()
作为上下文,它们起作用了。对于 bar1()
提供了两个整数,但没有返回任何内容,并且必须提供一个虚拟输出参数。对于 bar2()
没有给出输入值,但返回一个输出 int,它被转换为 star(int star) ,它可以正常工作并正确返回。
但是,对于 bar3()
,我在内部生成了一个 10 个元素的数组作为测试,它在 foo()
内从打印语句中正确返回,但我无法将数组返回到 {{1} }.我已经摆弄过各种涉及指针的语句,但是如果数组被初始化,则返回一个零列表,如果没有,则返回垃圾列表。
如何正确返回数组?
解决方法
在这次通话中
foo(xd,3,0)
数组指示符 xd
被转换为指向它的第一个元素的指针,函数处理这个值的副本。
在函数内这个语句
*(int*)ret_val = *p;
只是将数组xd
的第一个元素更改为指针p
指向的数组第一个元素的值。
数组没有复制赋值运算符。例如,您不能将一个数组分配给另一个数组
int a[10] = { /*...*/ };
int b[10] = { /*...*/ };
a = b;
所以这段代码片段
int* p = new int[10];
p = bar3();
// Add a loop to test out that the array has been read from bar3(),which works.
*(int*)ret_val = *p;
没有意义。此外,似乎存在内存泄漏,因为起初指针 p
被分配了已分配内存的地址
int* p = new int[10];
然后用函数 bar3
返回的值重新赋值。
p = bar3();
,
您可以编写如下所示的 foo
(在 C 中,因为这个问题最初被标记)。评论显示如何考虑ret_val
。请注意,bar3
的界面已更改。
/* ret_val is a pointer to some type T,a "T *",that has been converted to
"void *". To use it,we convert it back to its original type "T *".
*/
foo(void *ret_val,int mode,int num_params,...)
{
va_list args;
va_start(args,num_params);
switch (mode)
{
case 1:
{
// T is void. Nothing is returned via ret_val.
int a = va_arg(args,int);
int b = va_arg(args,int);
bar1(a,b);
}
break;
case 2:
{
/* We will return an int,so T is an int,and we convert ret_val
back to "int *".
*/
int val = bar1();
// Return val.
* (int *) ret_val = val;
}
break;
case 3:
{
/* We will return a pointer to an int,so T is an "int *",and
we convert ret_val back to "int **".
int *p = malloc(10 * sizeof p);
if (!p)
{
fprintf(stderr,"Error,memory allocation failed.\n");
exit(EXIT_FAILURE);
}
bar3(p);
// Return p.
* (int **) ret_val = p;
}
break;
}
va_end(args);
}
然后,对于案例 3,您可以使用以下命令调用 foo
:
int *xd;
foo(&xd,0);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。