在C中通过引用传递数组?

我怎样才能通过C引用的结构数组?

举个例子:

struct Coordinate { int X; int Y; }; SomeMethod(Coordinate *Coordinates[]){ //Do Something with the array } int main(){ Coordinate Coordinates[10]; SomeMethod(&Coordinates); } 

在C数组中作为指针传递给第一个元素。 它们是唯一没有真正通过值传递的元素(指针是按值传递的,但是数组没有被复制)。 这允许被调用的函数修改内容。

 void reset( int *array, int size) { memset(array,0,size * sizeof(*array)); } int main() { int array[10]; reset( array, 10 ); // sets all elements to 0 } 

现在,如果你想要的是改变数组本身(元素的数量…),你不能用堆栈或全局数组来做到这一点,只能在堆中dynamic分配内存。 在这种情况下,如果你想改变指针,你必须传递一个指针:

 void resize( int **p, int size ) { free( *p ); *p = (int*) malloc( size * sizeof(int) ); } int main() { int *p = (int*) malloc( 10 * sizeof(int) ); resize( &p, 20 ); } 

在编辑问题中,您特别要求传递一系列结构。 你有两个解决scheme:声明一个typedef,或者明确你正在传递一个结构:

 struct Coordinate { int x; int y; }; void f( struct Coordinate coordinates[], int size ); typedef struct Coordinate Coordinate; // generate a type alias 'Coordinate' that is equivalent to struct Coordinate void g( Coordinate coordinates[], int size ); // uses typedef'ed Coordinate 

你可以在声明的时候typedef这个types(这是C语言中常见的习惯用法):

 typedef struct Coordinate { int x; int y; } Coordinate; 

在这里扩大一些答案…

在C中,当一个数组标识符出现在不是作为&或sizeof的操作数的上下文中时,标识符的types被隐式地从“T的N元素数组”转换为“指向T的指针”,其值是隐式设置为数组中第一个元素的地址(与数组本身的地址相同)。 这就是为什么当你将数组标识符作为parameter passing给一个函数时,函数会接收一个指向基types的指针,而不是一个数组。 由于您不能通过查看指向第一个元素的指针来判断数组的大小,因此必须将其作为单独的parameter passing。

 struct Coordinate { int x; int y; }; void SomeMethod(struct Coordinate *coordinates, size_t numCoordinates) { ... coordinates[i].x = ...; coordinates[i].y = ...; ... } int main (void) { struct Coordinate coordinates[10]; ... SomeMethod (coordinates, sizeof coordinates / sizeof *coordinates); ... } 

有几种将数组传递给函数的替代方法。

有一个指向T数组的指针,而不是一个指向T的指针。你会声明这样一个指针为

 T (*p)[N]; 

在这种情况下,p是指向T的N元素数组的指针(与T * p [N]相反,其中p是指向T的N元素数组)。 所以你可以传递一个指向数组的指针,而不是指向第一个元素的指针:

 struct Coordinate { int x; int y }; void SomeMethod(struct Coordinate (*coordinates)[10]) { ... (*coordinates)[i].x = ...; (*coordinates)[i].y = ...; ... } int main(void) { struct Coordinate coordinates[10]; ... SomeMethod(&coordinates); ... } 

这种方法的缺点是数组的大小是固定的,因为指向10个元素的T数组的指针与指向20个T元素数组的指针是不同的types。

第三种方法是将数组包装在一个结构中:

 struct Coordinate { int x; int y; }; struct CoordinateWrapper { struct Coordinate coordinates[10]; }; void SomeMethod(struct CoordinateWrapper wrapper) { ... wrapper.coordinates[i].x = ...; wrapper.coordinates[i].y = ...; ... } int main(void) { struct CoordinateWrapper wrapper; ... SomeMethod(wrapper); ... } 

这种方法的优点是你不用指针。 缺点是数组大小是固定的(同样,T的10个元素的数组与T的20个元素的数组是不同的types)。

C语言不支持任何types的引用。 最接近的等效是将一个指针传递给types。

这是两种语言的一个人为的例子

C ++风格的API

 void UpdateValue(int& i) { i = 42; } 

最相近的C等价物

 void UpdateValue(int *i) { *i = 42; } 

在普通的C中,你可以在你的API中使用指针/大小的组合。

 void doSomething(MyStruct* mystruct, size_t numElements) { for (size_t i = 0; i < numElements; ++i) { MyStruct current = mystruct[i]; handleElement(current); } } 

使用指针最接近于C中可用的引用

也要知道,如果你正在一个方法中创build一个数组,你不能返回它。 如果你返回一个指向它的指针,当函数返回时它将被从堆栈中移除。 你必须把内存分配到堆上,并返回一个指针。 例如。

 //this is bad char* getname() { char name[100]; return name; } //this is better char* getname() { char *name = malloc(100); return name; //remember to free(name) } 

数组默认通过引用有效传递。 实际上,第一个元素的指针的值被传递。 因此接收这个的函数或方法可以修改数组中的值。

 void SomeMethod(Coordinate Coordinates[]){Coordinates[0].x++;}; int main(){ Coordinate tenCoordinates[10]; tenCoordinates[0].x=0; SomeMethod(tenCoordinates[]); SomeMethod(&tenCoordinates[0]); if(0==tenCoordinates[0].x - 2;){ exit(0); } exit(-1); } 

这两个调用是等价的,出口值应该是0;

嘿这里的人是一个简单的testing程序,显示如何分配和使用新的或malloc传递数组。 只需剪切,粘贴并运行它。 玩的开心!

 struct Coordinate { int x,y; }; void resize( int **p, int size ) { free( *p ); *p = (int*) malloc( size * sizeof(int) ); } void resizeCoord( struct Coordinate **p, int size ) { free( *p ); *p = (Coordinate*) malloc( size * sizeof(Coordinate) ); } void resizeCoordWithNew( struct Coordinate **p, int size ) { delete [] *p; *p = (struct Coordinate*) new struct Coordinate[size]; } void SomeMethod(Coordinate Coordinates[]) { Coordinates[0].x++; Coordinates[0].y = 6; } void SomeOtherMethod(Coordinate Coordinates[], int size) { for (int i=0; i<size; i++) { Coordinates[i].x = i; Coordinates[i].y = i*2; } } int main() { //static array Coordinate tenCoordinates[10]; tenCoordinates[0].x=0; SomeMethod(tenCoordinates); SomeMethod(&(tenCoordinates[0])); if(tenCoordinates[0].x - 2 == 0) { printf("test1 coord change successful\n"); } else { printf("test1 coord change unsuccessful\n"); } //dynamic int int *p = (int*) malloc( 10 * sizeof(int) ); resize( &p, 20 ); //dynamic struct with malloc int myresize = 20; int initSize = 10; struct Coordinate *pcoord = (struct Coordinate*) malloc (initSize * sizeof(struct Coordinate)); resizeCoord(&pcoord, myresize); SomeOtherMethod(pcoord, myresize); bool pass = true; for (int i=0; i<myresize; i++) { if (! ((pcoord[i].x == i) && (pcoord[i].y == i*2))) { printf("Error dynamic Coord struct [%d] failed with (%d,%d)\n",i,pcoord[i].x,pcoord[i].y); pass = false; } } if (pass) { printf("test2 coords for dynamic struct allocated with malloc worked correctly\n"); } //dynamic struct with new myresize = 20; initSize = 10; struct Coordinate *pcoord2 = (struct Coordinate*) new struct Coordinate[initSize]; resizeCoordWithNew(&pcoord2, myresize); SomeOtherMethod(pcoord2, myresize); pass = true; for (int i=0; i<myresize; i++) { if (! ((pcoord2[i].x == i) && (pcoord2[i].y == i*2))) { printf("Error dynamic Coord struct [%d] failed with (%d,%d)\n",i,pcoord2[i].x,pcoord2[i].y); pass = false; } } if (pass) { printf("test3 coords for dynamic struct with new worked correctly\n"); } return 0; }