C函数返回数组

我相对知道C,我习惯用Java编程,所以我发现C在数组方面有点困难。 在这种情况下,我仍然赞同自己:

int a []; int* a; int *a; 

在java中,我会做这样的事情来返回一个函数中的数组:

 int [] returnArr(int [] a){ ... modify a ... return a; } int [] a = {...}; int [] b = returnArr(a); ## 

我怎么能在C中做同样的事情,特别是##的部分。

编辑:我有这个function:

 float *normalizeValues(float *v, float maxY){ int size = sizeof(v) / sizeof(float); float max = findMax(v); float ratio = maxY / max; int i; for(i = 0; i < size ; ++i){ v[i] = v[i] * ratio; } return v; } 

我正在做以下事情:

 float vert [] = {306, 319, 360, 357, 375, 374, 387, 391, 391, 70, 82, 94, 91, 108, 114, 125, 127, 131}; int i = 0; float *vert2; vert2 = normalizeValues(vert, 0.7); for(i = 0; i < sizeof(vert2) / sizeof(float); ++i){ fprintf(stdout,": %f\n",vert2[i]); } 

输出只有1个元素。

编辑:直接回答您更新的问题:您必须传递数组的大小。 C没有像Java那样存储数组大小的机制。 如果编译器知道数组的大小,因为数组是全局或局部变量,而不是动态分配,那么您可以使用sizeof()运算符。 否则,您必须分别知道大小,或使用数组中的sentinel值(例如最后的0.0或NULL)。

至于数组,指针和参数一般,见下文:

您将返回一个指向数组的指针,该指针用’*’语法表示:

 int *returnArr(int[] a) { // modify a... return a; } int a[] = { ... }; int *b; b = returnArr(a); 

有几点需要注意:

  • 您不能在涉及非常量表达式的变量声明中进行赋值(例如,函数调用)。 不过,这可能在C99中有所改变。
  • 括号位于变量名称之后,与Java不同,它们是类型的一部分。 尽管Java的语法更加一致,但在C中并不常见,因为您经常在变量声明的括号中给出数组大小:

    int a[3] = { ... };

  • 没有办法指定函数返回数组而不是普通指针。 在C中,数组引用衰减为指针(尽管指针和数组并不是通常所声称的那样)。 这意味着无论何时传递数组,C只提供传递指向数组的指针的方法。 整个数组实际上并未复制。 碰巧,数组的名称也是指向数组第一个元素的指针。

另请注意user268396在回答中的内容。 如果你打算创建一个新数组并返回它,你需要动态分配数组,或者传入一个指向已经分配的数组的指针(这似乎是你在做什么) 。

你不能。 当函数返回时,堆栈帧将被清除(通常),并且生成的数组将被破坏。 但是,您可以编辑函数原型以接受指向要修改的数组的指针。 这种函数参数称为“输出参数”。 例:

 void function func(int a, int b, int[2] to_modify) { to_modify[0] = a; to_modify[1] = b; } int main() { int foo[2]; func(1, 2, foo); printf("Result: foo[0] = %d, foo[1] = %d\n", foo[0], foo[1]); return 0; } 

这将打印“结果:foo [0] = 1,foo [1] = 2”。

希望这可以帮助

  #include void change(int *c)/*Pointer c now has the first location of the array a[]*/ { *(c+0) = 0;/*assign values to the array by adding step-size to the first array position*/ *(c+1) = 1; *(c+2) = 2; *(c+3) = 3; *(c+4) = 4; } main() { int a[5]={10,20,30,40,50}; /* Declare and Assign an array a[] of size 5.*/ int *b = a; /*Declare and assign a Pointer to the location of the array.*/ change(b); /*pass the pointer(which is now pointing to first position of array) to the change() function.*/ printf("%d,%d,%d,%d,%d,",a[0],a[1],a[2],a[3],a[4]);/*Print the changed value.*/ } 

输出:0,1,2,3,4,

从Java的角度来看,指针就像(不完全是)对象引用一样。

 Object O; O = New SomeClassName(); 

像对象引用一样,O指向SomeClassName类型的某个实际对象,C中的指针也是如此:

 int *b; b = &a; 

变量b只是指向a的地址位置。 深入研究数组概念:

 int a[5]; int *b = a; 

在这里我们只是说先生* b指向组a的第一个位置,即a [0]

现在C中的电源指针是从现在开始的,在此之后:

 *b means a[0] *(b+1) means a[1] *(b+2) means a[2] *(b+3) means a[3] *(b+4) means a[4] 

这意味着你改变了*(b + 4),你正在改变一个[4]。

 int* returnArr(int a[]){ //modify a return a; } 

需要注意的是,当您在函数的参数列表中使用数组时,它将被转换为指针。 所以在main(…)的声明中, char *argv[]char **argv实际上是相同的。 在这种情况下, int a[]int* a是相同的。 但是数组和指针不是一回事。

以下面的代码为例:

 int a[10]; int main(){ int *p = a; p[5] = 4; return p[5]; } 

p是指针,当我们访问p [i]时,注意p的地址不是a的地址,p的内容是a的地址。 然后代码将:

  1. 访问内存以获取p的内容,即a的地址。
  2. 根据i和指针类型(int)计算偏移量。
  3. 访问内存以获得结果。

a是int数组,如果我们访问a [i],a的地址只是[0]的地址,代码将:

  1. 根据i和int类型计算偏移量。
  2. 访问内存。

指针和数组是不同的类型。 因此,如果在一个文件中声明int * p并在该文件中使用它,但将p定义为另一个文件中的数组,则会导致问题。

您可能也想知道在ANSI中,int * p = a,如果您使用数组(其名称)作为表达式,编译器会将其转换为指针,指向数组的第一个元素。

根据Jim Balter的评论更新

如果使用数组(其名称)作为表达式,编译器将不会始终将其转换为指针,指向数组的第一个元素。 例如,在sizeof(p-> q-> a)中,p-> q-> a是一个表达式,但如果a是一个数组,则它不会转换为指针。

“除非它是sizeof运算符或一元运算符的操作数,或者是用于初始化数组的字符串文字,否则具有类型”数组’类型’的表达式将转换为类型为”指针的表达式键入”指向数组对象的初始元素。

在C中,您只能在函数中返回数组的指针。 例如,如果要在函数中返回字符串(char数组),则可以返回指向空结束字符串的指针。 如果要返回其他类型的数组(int,用户定义的struct等),可以分配一些内存来存储数组,并返回数组的指针,返回参数中数组的大小。 例:

 int *function(int *size) { *size = 10; int *intP = (int *)malloc((*size)*sizeof(int)); return intP; }