我来自c#,这给我带来的问题比我预期的要多。我没有看到这方面的直接解决方案。我是C的新手,只是玩它,我尝试过的所有各种实现,从使用结构到传递指针都没有完成任务。 (本地值不变)。有人可以给我一个简单干燥的例子吗?
以下是我的代码示例
#include <stdio.h>
//alter values based on input
int * doStuff(int a, int b){
int input;
int arr[2]
scanf("%d", &option);
switch(option);
case 1:
arr[0] = a-2;
arr[1] = b;
return arr;
break;
case 2:
arr[0] = a;
arr[1] = b-2;
return arr;
break;
default:
return a, b;
}
main(){
int a = 20;
int b = 20;
int returnedObject[2];
//what i need is like in c# how I can do this
returnedObject = doStuff(a, b);
a = returnedObject[0];
b= returnedObject[1];
}
我需要传递值,更改它们,返回它们,并设置局部变量。我完全迷失了一些更复杂的例子。来自c#指针,数组,它们如何工作正在失去我,它并不像我预期的那么简单。
答案 0 :(得分:2)
C中的函数不能返回数组类型,也不能将数组作为赋值的目标。所以像
这样的代码int returnedObject[2];
returnedObject = doStuff( a, b );
无法正常工作。 C函数可以将指针返回到数组,但我认为你不想进入它。
C函数不能返回多个对象,也不支持多个赋值。
如果您的两个值是某些较大的聚合类型的逻辑属性,则可以使用struct
类型返回具有多个属性的单个对象,例如
struct result { int x, int y };
struct result doStuff( int a, int b )
{
struct result ret = {a, b}; // initialize struct with inputs
...
case 1:
ret.x = a-2;
break; // y remains unchanged
case 2:
ret.y = b-2;
break; // x remains unchanged
...
return ret;
}
你可以称之为
struct result stuff;
stuff = doStuff( a, b );
或者,您可以将指针传递给您的值并根据需要更新它们:
void doStuff( int *a, int *b )
{
...
case 1:
*a = *a - 2;
break;
case 2:
*b = *b - 2;
break;
}
你可以称之为
doStuff( &a, &b );
在这种情况下,您实际上并没有向调用者返回任何内容。
您可以将数组作为参数传递给函数,如下所示:
void doStuff( int a, int b, int *result )
{
result[0] = a;
result[1] = b;
...
case 1:
result[0] = a - 2;
break;
case 2:
result[1] = b - 2;
break;
...
}
你可以称之为
int results[2];
int a;
int b;
...
doStuff( a, b, results );
请注意,当我们将数组表达式传递给函数时,其类型从int [2]
更改为int *
。除非它是sizeof
或一元&
运算符的操作数,或者是用于初始化另一个数组的字符串文字,否则类型为“N元素数组”的表达式 T
“将被转换(”衰减“)为”指向T
的指针“的表达式,表达式的值将是数组的第一个元素的地址。在大多数情况下,C中的数组表达式会失去“数组” 1 。您可以在指针表达式上使用下标运算符[]
,就像使用数组表达式一样(数组索引操作a[i]
定义为*(a + i)
),但指针不是数组,反之亦然。
<小时/> 1。请注意,我说的是表达式,而不是对象。数组对象始终保持数组对象
答案 1 :(得分:1)
返回类型int *
。
创建一个本地变量int *result = malloc(sizeof(int) * 2);
并将a
和b
或您需要返回的任何内容放在result
中。
调用该函数时,将结果分配给int *
。
int *res;
res = doStuff(a, b);
a = res[0];
b = res[1];
malloc
在堆上为result
分配空间。它的输入是你需要的字节数。
2 int
s,每个int
4个字节 - &gt; 8个字节== 2*sizeof(int)
问题在于,每次调用函数时,都会继续分配越来越多的空间。 C不会为您进行垃圾回收,所以当您使用int *res
完成后,您应该通过调用free(res)
来free该空间。
更多详情:
在C#中,您将初始化一个这样的数组:int[] result = new result[2];
你们每个人都试过像这样打印一个数组Console.WriteLine(myarray);
。它没有工作吗? C#我相信打印像System.Int32[]
。如果你用Java(System.out.println(myarray);
)这样做,它会打印一些奇怪的数字。
该数字实际上是数组的地址。
引用数组myarray
时,实际上是引用数组的地址。当您执行myarray[1]
之类的操作时,您将获得myarray
的地址,并添加1*sizeof(int)
并获取该值。
在C中,您可以以典型的方式定义数组:int arr[2];
,它为2个整数分配空间。
或者,您可以执行:int *arr;
定义指针(或地址)。但是,您需要告诉它为整数分配空间。就像现在一样,arr
并没有真正指向任何事物。您可以通过调用malloc
:arr = malloc(2*sizeof(int));
来分配空间,它为2个整数动态分配空间。
现在你可以把东西放在你的数组中了。 arr[0] = 1
。
[]
实际上正在进行指针运算。
arr[1] is the same as *(arr + 1)
arr + 1
获取数组的地址并向其中添加1。 C看到你正在添加int *
所以它将1解释为1 int(4字节)。 *
运算符取消引用地址,这意味着它跟随指针并获取存储在该地址的值。
如果打印arr
为您提供0x1000
,则arr+1
会为您提供0x1004
,而*
会返回0x1004
处存储的整数。
在函数中返回数组。
在C中,你不能像C#(int[] function(...)
)那样返回一个数组,但你可以返回一个指针(int *function(...)
),你可以像数组一样使用它(见上文)例子)。
您要使用malloc
的原因是因为malloc
在堆上分配空间,因此您可以在函数返回后使用该数组。如果您定义了一个类似int arr[2];
的数组,则会在堆栈上分配空间,并且在函数返回后数组不会持久存在。
也许您应该查看教程以了解有关指针的更多信息。我认为我的答案过于冗长,与问题并不完全相关。
答案 2 :(得分:1)
简单的解决方案(通过引用/指针传递允许更改存储的值)
#include <stdio.h>
//alter values based on input
void doStuff(int *a, int *b, int option)
{
switch(option)
{
case 1:
// a decremented by 2, b is unchanged
*a = *a - 2;
break;
case 2:
// b decremented by 2, a is unchanged
*b = *b - 2;
break;
default:
// a and b are unchanged
break;
}
}
int main()
{
int a = 20;
int b = 20;
int option;
printf("Enter option (1 or 2):\n");
scanf("%d", &option);
printf("BEFORE doStuff() :: a = %d, b = %d\n", a, b);
doStuff(&a, &b, option);
printf("AFTER doStuff() :: a = %d, b = %d\n", a, b);
return 0;
}
答案 3 :(得分:1)
您可以使用结构包装数组以直接返回它。
#include <stdio.h>
struct doStuffRet {
int arr[2];
};
//alter values based on input
struct doStuffRet doStuff(int a, int b){
int option;
struct doStuffRet r = {{a, b}};
scanf("%d", &option);
switch(option) {
case 1:
r.arr[0] = a-2;
r.arr[1] = b;
return r;
break;
case 2:
r.arr[0] = a;
r.arr[1] = b-2;
return r;
break;
default:
return r;
}
}
int main(void){
int a = 20;
int b = 20;
struct doStuffRet returnedObject;
//what i need is like in c# how I can do this
returnedObject = doStuff(a, b);
a = returnedObject.arr[0];
b = returnedObject.arr[1];
printf("%d %d\n", a, b);
return 0;
}