How can I pass an array of structs 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);
}
In C arrays are passed as a pointer to the first element. They are the only element that is not really passed by value (the pointer is passed by value, but the array is not copied). That 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 what you want is changing the array itself (number of elements...) you cannot do it with stack or global arrays, only with dynamically allocated memory in the heap. In that case, if you want to change the pointer you must pass a pointer to it:
void resize( int **p, int size ) {
free( *p );
*p = malloc( size * sizeof(int) );
}
int main() {
int *p = malloc( 10 * sizeof(int) );
resize( &p, 20 );
}
In the question edit you ask specifically about passing an array of structs. You have two solutions there: declare a typedef, or make explicit that you are passing an struct:
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 typedef the type as you declare it (and it is a common idiom in C):
typedef struct Coordinate {
int x;
int y;
} Coordinate;
To expand a little bit on some of the answers here...
In C, when an array identifier appears in a context other than as an operand to either & or sizeof, the type of the identifier is implicitly converted from "N-element array of T" to "pointer to T", and its value is implicitly set to the address of the first element in the array (which is the same as the address of the array itself). That's why when you just pass the array identifier as an argument to a function, the function receives a pointer to the base type, rather than an array. Since you can't tell how big an array is just by looking at the pointer to the first element, you have to pass the size in 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 a couple of alternate ways of passing arrays to functions.
There is such a thing as a pointer to an array of T, as opposed to a pointer to T. You would declare such a pointer as
T (*p)[N];
In this case, p is a pointer to an N-element array of T (as opposed to T *p[N], where p is an N-element array of pointer to T). So you could pass a pointer to the array as opposed to 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 array size is fixed, since a pointer to a 10-element array of T is a different type from a pointer to a 20-element array of T.
A 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 aren't mucking around with pointers. The disadvantage is that the array size is fixed (again, a 10-element array of T is a different type from a 20-element array of T).
The C language does not support pass by reference of any type. The closest equivalent is to pass a pointer to the type.
Here is a contrived example in both languages
C++ style API
void UpdateValue(int& i) {
i = 42;
}
Closest C equivalent
void UpdateValue(int *i) {
*i = 42;
}
also be aware that if you are creating a array within a method, you cannot return it. If you return a pointer to it, it would have been removed from the stack when the function returns.
you must allocate memory onto the heap and return a pointer to that.
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)
}
Arrays are effectively passed by reference by default. Actually the value of the pointer to the first element is passed. Therefore the function or method receiving this can modify 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);
}
The two calls are equivalent, and the exit value should be 0;
In plain 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 to call-by-reference available in C.
Hey guys here is a simple test program that shows how to allocate and pass an array using new or malloc. Just cut, paste and run it. Have fun!
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;
}
Related
Currently, I have a struct camera that holds two fixed size variables f and p
struct point {
double x, y, z;
};
struct camera {
struct point f[5], p[5];
};
Making f and p flexible results in error. I followed the instructions given in this SO question and decided to go for non-struct variables and pass them to functions instead which resulted in long function call syntax and messy structure.
My question, although subjective, is: what is the best approach to have two flexible arrays that can be accessed via one point (similar to struct, etc.)?
A non flexible array approach follows that, IMO, addresses OP's higher level problem of "long function call syntax and messy structure" with a cleaner pair of struct point pointers.
struct camera {
size_t size; // add size member
struct point *f;
struct point *p;
};
bool camera_initialize(struct camera *cam, size_t size) {
// Use 1 or 2 allocations
cam->f = malloc(sizeof *(cam->f) * 2 * size);
if (cam->f) {
cam->p = cam->f + size;
cam->size = size;
return false; // success
} else {
cam->p = cam->f = NULL;
cam->size = 0;
return size > 0; // fail if size was not 0
}
}
void camera_uninitialize(struct camera *cam) {
free(cam->f);
cam->p = cam->f = NULL;
cam->size = 0;
}
Sample usage
int main() {
size_t n = foo();
struct camera cam;
if (camera_initialize(&cam, n)) return EXIT_FAILURE;
bar(cam.f, cam.n);
bar(cam.p, cam.n);
camera_uninitialize(&cam);
}
By definition you can't have two flexible array members. A flexible array member must be the last in the structure, there can only be a single "last" element.
But I sense you apparently need to pair up f and p, so why not aggregate them? Then you can have a flexible array member of those pairs:
#include <stdio.h>
#include <stdlib.h>
struct point {
double x, y, z;
};
struct camera {
char dummy;
struct {
struct point f, p;
} pairs[];
};
int main(void) {
struct camera *c = malloc(sizeof(*c) + sizeof(c->pairs[0])*5);
return 0;
}
Note the use of C99's support for flexible array members.
Here is an approach that mimics two flexible arrays of identical type: make one flexible array that holds both arrays, and add a pointer into the array at the position where the second flexible array starts:
struct camera {
struct point *p;
struct point f[];
};
When you allocate camera, provision the space for both arrays, and add it to the "raw" sizeof(struct camera). Let's say your first array has n elements, and the second one has m. Then you initialize your camera as follows:
struct camera *c = malloc(sizeof(*c)+(n+m)*sizeof(struct point));
c->p = &(c->f[n]); // Point "p" to the beginning of the second array
for (int i = 0 ; i != n ; i++) {
c->f[i] = ... // Init points in f
}
for (int i = 0 ; i != m ; i++) {
c->p[i] = ... // Init points in p
}
This question already has answers here:
malloc-ating multidimensional array in function
(7 answers)
Closed 7 years ago.
At first, it may sound normal if I free the allocation within the function, but it's not the case. As I'm writting these lines, I've found a work around, but I would like to keep a certain homogeneity in my code and would prefer to keep it the way it ways but you know working properly, so is there another solutions or my workaround is the only option?
The main function:
void main(void)
{
SHead head; // Custom struct
unsigned char **array = NULL; // pointer to 2D array
allocArray2D(&head, array) // the function signature: (SHead*, unsigned char**)
// here, the array pointer is still NULL (0x0)
//...
return EXIT_SUCCESS;
}
The allocation function malloc a very small amount of memory around 21 unsigned char* and for each simple pointer 21 unsigned char.
Within the function, the pointer is fine and points to a proper address.
So my work around was modify the function from:
void allocArray(SHead* h, unsigned char** arr)
{
int x, y, i;
getsize(head, *x, *y);
arr = (unsigned char**)malloc(sizeof(unsigned char*)*y);
if(arr)
printf(">> Erro allocating memory\n"), return;
for(i =0; i<y; i++)
{
arr[i] = (unsigned char)malloc(sizeof(unsigned char)*x);
}
}
to the following:
unsigned char** allocArray(SHead*)
{
int x, y, i;
unsigned char **arr;
getsize(head, *x, *y);
arr = (unsigned char**)malloc(sizeof(unsigned char*)*y);
if(arr)
printf(">> Erro allocating memory\n"), return;
for(i =0; i<y; i++)
{
arr[i] = (unsigned char)malloc(sizeof(unsigned char)*x);
}
return arr; // returning the address
}
As I said earlier, I'd like to keep homogeneity within my code and would prefer to keep a function signature similar to other function I have. My workaround work properly. And I'm wondering if it is the only solution, or perhaps I am missing something.
EDIT: Following the comments I added more code.
Thank you,
Alex.
You have to pass a pointer to the 2dimensional array to your function, to write in the function to the value behind the pointer:
SHead head; // Custom struct
unsigned char **array = NULL; // pointer to 2D array
allocArray2D(*head, &array)
// ^ address of array
-
void allocArray(SHead* head, unsigned char*** pArray)
// ^ pointer to char** because its an output parameter
{
int x, y, i;
getsize( head, &x, &y );
*pArray = malloc( y * sizeof( unsigned char * );
// ^ assigne somtething to the variable array refered by the pointer pArray
if( *pArray == NULL )
{
printf(">> Erro allocating memory\n")
return;
}
for ( i = 0; i < y; i ++ )
(*pArray)[i] = malloc( x * sizeof( unsigned char ) );
}
Note, what you did was to pass a NULL-pointe to the function allocArray.
An other solution would be to return the allocated memory by the return value of function allocArray:
SHead head; // Custom struct
unsigned char **array = NULL;
array = allocArray( &head );
-
unsigned char** allocArray( SHead* head )
{
int x, y, i;
getsize( head, &x, &y );
unsigned char** arr = malloc( y * sizeof( unsigned char * );
if( arr == NULL )
{
printf(">> Erro allocating memory\n")
return;
}
for ( int i = 0; i < y; i ++ )
arr[i] = malloc( x * sizeof( unsigned char ) );
return arr;
}
If I have understood you correctly what you need is something like the following
For simplicity I excluded the parameter that refers to the structure.
void allocArray2D( unsigned char ***a, size_t n )
{
*a = malloc( n * sizeof( unsigned char * ) );
for ( size_t i = 0; i < n; i++ ) ( *a )[i] = malloc( n * sizeof( unsigned char ) );
}
//...
unsigned char **array = NULL; // pointer to 2D array
allocArray2D( &array, 21 );
If you want that the original object would be changed after passing it to a function then you have to pass it by reference.
Your call looks very strange.
First, you are passing *head. head seems to be an uninitialised variable, so passing *head seems badly wrong.
Second, the function called has no way of seeing array. Your call is equivalent to allocArray2D (*head, NULL) and not having the array variable at all. This also seems very wrong.
i am fairly new to c and struggling to properly use the C stdlib qsort() function.
This is relevant to education and as such i am only allowed to use C99 and standard libraries if this is important.
I have a list of items taken from a HashTable and put into a HashItem **array but then when sorting this i am struggling with the compare function, i cannot get the correct value out of the struct. I have looked around and seen a few solutions but they all seem to lead to a
[Error] dereferencing pointer to incomplete type
Here is the struct :
typedef struct {
char *word;
int occurences;
} HashItem;
And i am interested in comparing and sorting by the occurences value.
Here is the bit of code which calls the qsort:
int n = array->number_of_values;
HashItem **standard_array = array_getarray(array);
qsort(standard_array, n, sizeof(HashItem*), compare_func);
Here is the compare function:
int compare_func(const void *a, const void *b){
const struct HashItem* aa = (HashItem*)a;
const struct HashItem* bb = (HashItem*)b;
int val_1 = aa->occurencies;
int val_2 = bb->occurencies;
if(val_1 == val_2){
return 0;
}else if(val_1 > val_2){
return 1;
}else{
return -1;
}
}
Sorry for the formatting, i am new to asking questions here.
I hope you can help thankyou.
Array code :
/*DynArray is a dynamically resizing array that is used to hold values and retain size data throughout*/
typedef struct{
int number_of_values;
int capacity;
HashItem **items;
}DynArray;
/*Method to create a new dynamic array and return it */
DynArray* array_new(int file_size){
DynArray *array = malloc(sizeof(DynArray));
array->number_of_values = 0;
array->capacity = file_size / 10;
printf("capacity is %d " , array->capacity);
array->items = malloc(sizeof(HashItem*)* array->capacity);
}
/*Method used to increase the size of the array and reallocate memory*/
void array_increase_if_full(DynArray *array){
if (array->number_of_values >= array->capacity){
array->capacity *= 1.25;
array->items = realloc(array->items, sizeof(HashItem)*array->capacity);
}
}
/*Method to add a string to the dynamic array specified */
void array_append(DynArray *array, HashItem *item){
array_increase_if_full(array);
array->items[array->number_of_values] = item;
//printf("item %s added \n at position %d ", array->items[array->number_of_values]->word, array->number_of_values);
array->number_of_values++;
}
/*Method used to get value at specified position for given array*/
HashItem *array_get(DynArray *array, int position){
if(position >= array->number_of_values || position <0){
printf("Index specified out of range");
exit(1);
}
//printf("item %s at position %d retrieved", array->items[position]->word, position);
return array->items[position];
}
HashItem **array_getarray(DynArray *array){
HashItem **toreturn[array->number_of_values];
int i;
for(i = 0; i < array->number_of_values; i++){
toreturn[i] = array_get(array, i);
}
return toreturn;
}
Printing the array from the main gives the correct unsorted values of word:occurences
Edit:
Thanks to everyone that took their time to help, it is now in a working state with Michaels suggestion, i no longer use the array_getarray() method and instead use:
int n = array->number_of_values;
int i;
HashItem **standard_array = malloc(n*sizeof(HashItem*));
for(i = 0; i < n; i++){
standard_array[i] = array_get(array, i);
printf("%s : %d \n" , standard_array[i]->word, standard_array[i]->occurences);
}
You structure declaration:
typedef struct {
char *word;
int occurences;
} HashItem;
declares a typedef name for an anonymous struct. There is a HashItem type that's a structure, but there is no struct HashItem type.
So when your compare_func() has the following declarations:
const struct HashItem* aa = (HashItem*)a;
const struct HashItem* bb = (HashItem*)b;
those struct HashItem* variables are pointers to a forward declared struct HashItem that has nothign to do with the HashItem strucuture above.
Just change those variable declarations to:
const HashItem* aa = (HashItem*)a;
const HashItem* bb = (HashItem*)b;
and/or change the declaration of the structure to:
typedef struct HashItem {
char *word;
int occurences;
} HashItem;
However, there's another issue (as mentioned in other answers): you are apparently sorting an array of pointers to HashItem objects, but your compare_function() is being written as if you're sorting an array of the objects (not pointers).
To address this:
int compare_func(const void *a, const void *b)
{
// get HashItem*'s from the HashItem**'s
const HashItem* aa = *((HashItem**)a);
const HashItem* bb = *((HashItem**)b);
int val_1 = aa->occurencies;
int val_2 = bb->occurencies;
if (val_1 == val_2) {
return 0;
} else if (val_1 > val_2) {
return 1;
} else {
return -1;
}
}
Finally (for now anyway), this function is returning the address to a local array, so the data it points to is no longer valid:
HashItem **array_getarray(DynArray *array){
HashItem **toreturn[array->number_of_values];
int i;
for(i = 0; i < array->number_of_values; i++){
toreturn[i] = array_get(array, i);
}
return toreturn;
}
I think you'll need to allocate the array you're retuning using malloc() or calloc() or something. But what I really think you need to do is step back and create some drawing of your data structures and think about the lifetime of the various objects contained in them and how those lifetimes can be tracked an managed so that you don't have leaks, double frees, or pointer dereferences to no longer valid objects.
Change qsort(standard_array, n, sizeof(HashItem), compare_func); to
qsort(standard_array, n, sizeof(HashItem*), compare_func);
In function void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
the third parameter size_t size stands for:
Size in bytes of each element in the array.
It now looks to me like your problems are all springing from the first definition.
/*DynArray is a dynamically resizing array that is used to hold values and retain size data throughout*/
typedef struct{
int number_of_values;
int capacity;
HashItem **items;
}DynArray;
I see no reason for items to be a double-pointer. The comment says it should contain values, but a double-pointer pointing to an array would contain pointers, not the ultimate values. I think this initial misstep is causing you to trip everywhere else. Change it to
...
HashItem *items;
...
and the rest should flow more naturally.
I have a struct that contains an int pointer
struct mystruct {
int *myarray;
};
I want to make a function that mallocates for mystruct and also initializes myarray. But, when I try to access an element of myarray, I get a seg. fault
void myfunction(struct mystruct *s, int len) {
s = malloc(sizeof(mystruct));
s->myarray = malloc(sizeof(int) * len);
int i;
for (i=0; i<len; i++) {
s->myarray[i] = 1;
}
}
main() {
struct mystruct *m;
myfunction(m, 10);
printf("%d", m->myarray[2]); ////produces a segfault
}
However, mallocating m in main seemed to solve my problem.
Revised Code:
void myfunction(struct mystruct *s, int len) {
int i;
s->myarray = malloc(sizeof(int) * len);
for (i=0; i<len; i++) {
s->myarray[i] = 1;
}
}
main() {
struct mystruct *m = malloc(sizeof(mystruct)); //this was in myfunction
myfunction(m,10);
printf("%d", m->myarray[2]); ///Prints out 1 like I wanted
}
Why did the 2nd attempt work and why did the first attempt not work?
The problem is that the first version assigns the result of malloc to a parameter, which effectively a local variable; the assigned value vanishes when the function returns
So, an alternative is to pass to the function a pointer to the location where you want to store the result of malloc. This is named pps in the code below. At the beginning of the function we do the malloc and assign to a local variable s. Then we do things with s. Then, just before the function exits, we assign the local variable s to the location pointed to by the parameter pps. *pps = s;
void myfunction(struct mystruct **pps, int len) { // note double "**"
struct mystruct *s = malloc(sizeof(mystruct);
s->myarray = malloc(sizeof(int) * len);
int i;
for (i=0; i<len; i++) {
s->myarray[i] = 1;
}
*pps = s; // now pass the alloc'ed struct back to main through parameter pps
}
Now, back in main we pass &m to the function. This passes a pointer to m to the function. When the function returns, the local variable m holds the value returned by malloc and passed through the parameter pps.
main() {
struct mystruct *m;
myfunction(&m, 10); // PASS THE ADDRESS OF m, not m itself
printf("%d", m->myarray[2]); // this will work now
}
How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.