Passing an array by reference in C?

How to pass an array of structures by reference in C?

As an example:

struct Coordinate { int X; int Y; }; SomeMethod(Coordinate *Coordinates[]){ //Do Something with the array } int main(){ Coordinate Coordinates[10]; SomeMethod(&Coordinates); } 
+54
c arrays pass-by-reference
Jul 09 '09 at 23:27
source share
7 answers

In C, arrays are passed as a pointer to the first element. This is the only element that is not passed by value (the pointer is passed by value, but the array is not copied). This allows the called function to modify the contents.

 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 } 

Now, if you want to change the array itself (the number of elements ...), you cannot do this with the stack or global arrays, only with dynamically allocated memory on the heap. In this case, if you want to change the pointer, you must pass the pointer to it:

 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 ); } 

In the editing question, you are asking about the transfer of an array of structures. You have two solutions: declare a typedef or indicate that you are passing a structure:

 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 

You can print a type when it is declared (and this is a common idiom in C):

 typedef struct Coordinate { int x; int y; } Coordinate; 
+112
Jul 09 '09 at 23:35
source share
— -

To expand some answers a bit here ...

In C, when an array identifier appears in a context other than the operand for either or sizeof, the identifier type is implicitly converted from an "N-element array T" to a "pointer to T" and its value is implicitly set to the address of the first element in the array (which matches the address of the array itself). Therefore, when you simply pass an array identifier as an argument to a function, the function gets a pointer to the base type, not the array. Since you cannot determine how large the array is, just by looking at the pointer to the first element, you must pass the size as a separate parameter.

 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); ... } 

There are several alternative ways to pass arrays to functions.

There is such a thing as a pointer to an array from T, unlike a pointer to T. You would indicate a pointer like

 T (*p)[N]; 

In this case, p is a pointer to an N-element array from T (unlike T * p [N], where p is an N-element array of a pointer to T). Thus, you can pass a pointer to an array, rather than a pointer to the first element:

 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); ... } 

The disadvantage of this method is that the size of the array is fixed, since a pointer to a 10-element array T is different from a pointer to a 20-element array T.

The third method is to wrap the array in a struct:

 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); ... } 

The advantage of this method is that you do not twitch with pointers. The disadvantage is that the size of the array is fixed (again, the 10-element array T is another type from the 20-element array T).

+8
Jul 10 '09 at 15:23
source share

C does not support passing by reference of any type. The closest equivalent is passing a pointer to a type.

Here is a contrived example in both languages

C ++ Style API

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

The closest equivalent to C

 void UpdateValue(int *i) { *i = 42; } 
+7
Jul 09 '09 at 23:29
source share

In simple C, you can use a pointer / size combination in your API.

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

Using pointers is the closest you can call to a link available in C.

+6
Jul 09 '09 at 23:36
source share

also remember that if you create an array inside a method, you cannot return it. If you return a pointer to it, it will be removed from the stack when the function returns. you must allocate memory in a heap and return a pointer to it. eg.

 //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) } 
+6
Jul 09 '09 at 23:42
source share

Arrays are by default passed by reference. In fact, the value of the pointer to the first element is passed. Therefore, a function or method receiving this can change the values ​​in the array.

 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); } 

Two calls are equivalent, and the output value must be 0;

+5
Jul 09 '09 at 23:51
source share

Hi guys, this is a simple test program that shows how to distribute and pass an array using new or malloc. Just cut, paste and run. Enjoy!

 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; } 
+2
Dec 08 '11 at 4:21
source share



All Articles