使用C返回一个数组

我对C来说比较新,我需要一些处理数组的方法。 来自Java编程,我习惯于能够说int [] method()为了返回一个数组。 不过,我发现用C语言你必须在返回数组时使用指针。 作为一个新的程序员,我真的不明白这一点,即使我看过很多论坛。

基本上,我试图编写一个返回在C中的字符数组的方法。我将提供一个数组的方法(让我们调用它的returnArray)。 它将从前面的数组中创build一个新的数组,并返回一个指向它的指针。 我只是需要一些帮助,如何获得这个开始,以及如何读取指针,一旦它被发送出arrays。 任何帮助解释这一点表示赞赏。

数组返回函数的build议代码格式

 char *returnArray(char array []){ char returned [10]; //methods to pull values from array, interpret them, and then create new array return &(returned[0]); //is this correct? } 

函数的调用者

 int main(){ int i=0; char array []={1,0,0,0,0,1,1}; char arrayCount=0; char* returnedArray = returnArray(&arrayCount); ///is this correct? for (i=0; i<10;i++) printf(%d, ",", returnedArray[i]); //is this correctly formatted? } 

我还没有testing过,因为我的C编译器目前不工作,但我想知道这一点

你不能从C中的函数返回数组。你也不能(不应该)这样做:

 char *returnArray(char array []){ char returned [10]; //methods to pull values from array, interpret them, and then create new array return &(returned[0]); //is this correct? } 

returned会创build自动存储持续时间,一旦离开其声明范围,即函数返回时,对它的引用将变为无效。

您将需要dynamic分配函数内部的内存或填充调用者提供的预分配的缓冲区。

选项1:

dynamic分配函数内部的内存(调用者负责释放ret

 char *foo(int count) { char *ret = malloc(count); if(!ret) return NULL; for(int i = 0; i < count; ++i) ret[i] = i; return ret; } 

像这样调用它:

 int main() { char *p = foo(10); if(p) { // do stuff with p free(p); } return 0; } 

选项2:

填充调用者提供的预先分配的缓冲区(调用者分配buf并传递给函数)

 void foo(char *buf, int count) { for(int i = 0; i < count; ++i) buf[i] = i; } 

并称之为如此:

 int main() { char arr[10] = {0}; foo(arr, 10); // No need to deallocate because we allocated // arr with automatic storage duration. // If we had dynamically allocated it // (ie malloc or some variant) then we // would need to call free(arr) } 

C对数组的处理与Java有很大不同,因此你必须相应地调整你的想法。 C中的数组不是一等对象(也就是说,在大多数情况下,数组expression式并不保留它的“数组性”)。 在C语言中,除了当数组expression式是sizeof或一元运算符时,“ T ”的N元素数组expression式将被隐式转换(“decay”)为一个types的expression式。 ,或者如果数组expression式是用来初始化声明中的另一个数组的string文字。

除此之外,这意味着您不能将数组expression式传递给一个函数,并将其作为数组types接收; 该函数实际上收到一个指针types:

 void foo(char *a, size_t asize) { // do something with a } int bar(void) { char str[6] = "Hello"; foo(str, sizeof str); } 

在对foo的调用中,expression式strchar [6]转换为char * ,这就是为什么foo的第一个参数被声明为char *a而不是char a[6] 。 在sizeof str ,由于数组expression式是sizeof运算符的操作数,因此它不会转换为指针types,因此您可以获得数组中的字节数(6)。

如果你真的感兴趣,你可以阅读丹尼斯·里奇的“C语言的发展”来理解这种治疗的来源。

其结果是函数不能返回数组types,这是好的,因为数组expression式不能作为赋值的目标。

最安全的方法是调用者定义数组,并将其地址和大小传递给应该写入的函数:

 void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize) { ... dstArray[i] = some_value_derived_from(srcArray[i]); ... } int main(void) { char src[] = "This is a test"; char dst[sizeof src]; ... returnArray(src, sizeof src, dst, sizeof dst); ... } 

另一种方法是让函数dynamic分配数组并返回指针和大小:

 char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize) { char *dstArray = malloc(srcSize); if (dstArray) { *dstSize = srcSize; ... } return dstArray; } int main(void) { char src[] = "This is a test"; char *dst; size_t dstSize; dst = returnArray(src, sizeof src, &dstSize); ... free(dst); ... } 

在这种情况下,调用者负责使用free库函数释放数组。

请注意,上面的代码中的dst是一个简单的char指针,而不是一个char数组的指针。 C的指针和数组语义是这样的,你可以将下标运算符[]应用于数组types指针types的expression式; src[i]dst[i]都将访问​​数组的第i个元素(即使只有src有数组types)。

可以声明一个指向T的N元素数组的指针,并执行类似的操作:

 char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE] { char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr); if (dstArr) { ... (*dstArr)[i] = ...; ... } return dstArr; } int main(void) { char src[] = "This is a test"; char (*dst)[SOME_SIZE]; ... dst = returnArray(src, sizeof src); ... printf("%c", (*dst)[j]); ... } 

上面的几个缺点。 首先,C的老版本期望SOME_SIZE是一个编译时常量,这意味着函数将只能使用一个数组大小。 其次,在应用下标代码之前,必须先取消引用指针。 在处理multidimensional array时,指向数组的指针可以更好地工作。

在你的情况下,你正在堆栈上创build一个数组,一旦你离开函数作用域,数组将被释放。 相反,创build一个dynamic分配的数组并返回一个指针。

 char * returnArray(char *arr, int size) { char *new_arr = malloc(sizeof(char) * size); for(int i = 0; i < size; ++i) { new_arr[i] = arr[i]; } return new_arr; } int main() { char arr[7]= {1,0,0,0,0,1,1}; char *new_arr = returnArray(arr, 7); // don't forget to free the memory after you're done with the array free(new_arr); } 

我并不是说这是针对给定问题的最佳解决scheme或首选解决scheme。 但是,记住函数可以返回结构可能是有用的。 虽然函数不能返回数组,但数组可以包装在结构中,函数可以返回结构,从而携带数组。 这适用于固定长度的数组。

  #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char v[10]; } CHAR_ARRAY; CHAR_ARRAY returnArray(CHAR_ARRAY array_in, int size) { CHAR_ARRAY returned; /* . . . methods to pull values from array, interpret them, and then create new array */ for (int i = 0; i < size; i++ ) returned.v[i] = array_in.v[i] + 1; return returned; // Works! } int main(int argc, char * argv[]) { CHAR_ARRAY array = {1,0,0,0,0,1,1}; char arrayCount = 7; CHAR_ARRAY returnedArray = returnArray(array, arrayCount); for (int i = 0; i < arrayCount; i++) printf("%d, ", returnedArray.v[i]); //is this correctly formatted? getchar(); return 0; } 

我邀请对这种技术的优点和缺点发表意见。 我没有打扰这样做。

这个可恶的实施呢?

array.h

 #define IMPORT_ARRAY(TYPE) \ \ struct TYPE##Array { \ TYPE* contents; \ size_t size; \ }; \ \ struct TYPE##Array new_##TYPE##Array() { \ struct TYPE##Array a; \ a.contents = NULL; \ a.size = 0; \ return a; \ } \ \ void array_add(struct TYPE##Array* o, TYPE value) { \ TYPE* a = malloc((o->size + 1) * sizeof(TYPE)); \ TYPE i; \ for(i = 0; i < o->size; ++i) { \ a[i] = o->contents[i]; \ } \ ++(o->size); \ a[o->size - 1] = value; \ free(o->contents); \ o->contents = a; \ } \ void array_destroy(struct TYPE##Array* o) { \ free(o->contents); \ } \ TYPE* array_begin(struct TYPE##Array* o) { \ return o->contents; \ } \ TYPE* array_end(struct TYPE##Array* o) { \ return o->contents + o->size; \ } 

main.c中

 #include <stdlib.h> #include "array.h" IMPORT_ARRAY(int); struct intArray return_an_array() { struct intArray a; a = new_intArray(); array_add(&a, 1); array_add(&a, 2); array_add(&a, 3); return a; } int main() { struct intArray a; int* it; int* begin; int* end; a = return_an_array(); begin = array_begin(&a); end = array_end(&a); for(it = begin; it != end; ++it) { printf("%d ", *it); } array_destroy(&a); getchar(); return 0; } 

你的方法将返回一个本地堆栈variables,将会失败。 要返回一个数组,在函数外创build一个,通过地址传递给函数,然后修改它,或者在堆上创build一个数组并返回该variables。 两者都可以工作,但是第一个不需要任何dynamic的内存分配来使它正常工作。

 void returnArray(int size, char *retArray) { // work directly with retArray or memcpy into it from elsewhere like // memcpy(retArray, localArray, size); } #define ARRAY_SIZE 20 int main(void) { char foo[ARRAY_SIZE]; returnArray(ARRAY_SIZE, foo); } 

你可以使用堆内存(通过malloc()调用),像这里报告的其他答案一样,但是你必须总是pipe理内存(每次调用你的函数时都使用free()函数)。 你也可以用一个静态数组来做到这一点:

 char* returnArrayPointer() { static char array[SIZE]; // do something in your array here return array; } 

你可以使用它而不用担心内存pipe理。

 int main() { char* myArray = returnArrayPointer(); /* use your array here */ /* don't worry to free memory here */ } 

在这个例子中,你必须在数组定义中使用static关键字来设置application-long数组的生命周期,所以在return语句后它不会被销毁。 当然,通过这种方式,您可以在整个应用程序生命周期中占用内存中的SIZE字节,因此请正确调整它的大小!

你可以使用这样的代码:

 char *MyFunction(some arguments...) { char *pointer = malloc(size for the new array); if (!pointer) An error occurred, abort or do something about the error. return pointer; // Return address of memory to the caller. } 

当你这样做的时候,内存应该被释放,通过传递地址来释放。

还有其他的select。 一个例程可能会返回一个指向某个数组(或者数组的一部分)的指针,这个数组是现有结构的一部分。 调用者可能会传递一个数组,而例程只是写入数组,而不是为新数组分配空间。

这里有一个不同的选项来传递string和返回string的一个小例子。

 //include DPI #include "svdpi.h" //include the IO files #include <stdio.h> //include string functions #include <string.h> //include use of malloc #include <stdlib.h> //to add the ability to use printf // same inputs as defined in SV /* function declaration text char stream passed as pointer value and text2 passed as pointer reference */ char * return_string_in_c( char *text, char **text2) { char *fix="This variable cannot be changed although it is a pointer, just as example";/*fix allocation and constant*/ char dest[50]="Variable array created in a function:";/* String array max 50 chars allocated*/ char *out = malloc(sizeof(char) * 100);/* Dynamic string max 100 chars allocated*/ /* Concatenate input text and put in out of strcat*/ strcat(out, text);/* initialize out using strcat and text string*/ printf("fix : |%s|,dest : |%s|,text : |%s|,out : |%s|\n", fix,dest,text,out); *text2=dest;/* allocate pointer value with dest*/ *text2=out;/* now do the same overwrite allocate pointer value with out*/ return out; } /* main */ void main() { char text[100]="from_main_text_variable";/*max 100 chars allocated*/ char *text2;/* pointer not allocated*/ char *point = return_string_in_c(text, &text2);/* &text2 passing by reference*/ printf("Final destination string : |%s|\n", text2); printf("point output : |%s|\n", point); } 

将你的数组声明为一个全局variables,这样每个函数都可以编辑它。 示例#include #include

 char a[1000]; void edit(char b); main() { edit(a); printf("%s", a); } void edit(char b) { for(int i=0;i<sizeof(b);i++) a[i]=i; }