realloc array of struct in c [duplicate] - c

I need to do a simple thing, which I used to do many times in Java, but I'm stuck in C (pure C, not C++). The situation looks like this:
int *a;
void initArray( int *arr )
{
arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( a );
// a is NULL here! what to do?!
return 0;
}
I have some "initializing" function, which SHOULD assign a given pointer to some allocated data (doesn't matter). How should I give a pointer to a function in order to this pointer will be modified, and then can be used further in the code (after that function call returns)?

You need to adjust the *a pointer, this means you need to pass a pointer to the *a. You do that like this:
int *a;
void initArray( int **arr )
{
*arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( &a );
return 0;
}

You are assigning arr by-value inside initArray, so any change to the value of arr will be invisible to the outside world. You need to pass arr by pointer:
void initArray(int** arr) {
// perform null-check, etc.
*arr = malloc(SIZE*sizeof(int));
}
...
initArray(&a);

Related

Why should we use a double pointer when we pass a dynamic array as a parameter to a function?

I am relatively new to programming, and im trying to understand some concepts with pointers. I got it for the most part, and i was looking in dinamic memory allocation, and i understood i need to create a pointer and the malloc function will return the first adress of the allocated space, which we put in the pointer created. That make a lot of sense because thats makes the dinamic vector just like a regular vector, right? Because a static vector also has the name of the vector a pointer to the first element. But why when i try to for example change the size of the vector with realloc in a function i understand i need to use a double pointer as a parameter. Something like this:
void function(int **vector){
*vector=(*int)realloc(*vector, sizeof(int)*n);
}
Can someone explain, thanks!
When a function declared as void function(int *vector) is called, it is passed only the value of an int *—just a pointer to the first element of a vector (an array). If this function is called with function(MyVector), then, inside the function, vector refers only to the copy of the value that is passed. It does not refer to MyVector, and changing vector will not change MyVector.
When a function declared as void function(int **vector) is called, it is passed the value of an int **—a pointer to a pointer to the first element of a vector. If this function is called with function(&MyVector), then, inside the function, vector refers to the copy of the pointer to the pointer. However, since it is a pointer to a pointer, then *vector refers to the pointer to the first element of the array. That is, *vector is not just a copy of the pointer, it is the actual pointer, the MyVector in the caller.
So, in the first function vector = realloc(…); does not change MyVector in the caller. In the second function, *vector = realloc(…); does change MyVector in the caller.
If you have a function like this
void f( T item );
where T is some type specifier and call it like
T object;
f( object );
then the function gets a copy of its argument. You can imagine this the following way
T object;
f( object );
//....
void f( /* T item */ )
{
T item = object;
// ...
}
So changes of the copy within the function dos not influence on the original object passed to the function as an argument.
To change the original object you have to pass it by reference. For example
void f( T *item )
{
*item = new_value;
//...
}
//...
T object;
f( &object );
If you have an object of the type int that you want to change within a function then just substitute the type specifier T for the type int and you will get.
void f( int *item )
{
*item = new_value;
//...
}
//...
int object;
f( &object );
If the object has the type int * then substitute T for int * and you will get
void f( int **item )
{
*item = new_value;
//...
}
//...
int *object;
f( &object );
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
void f( int *x )
{
*x = 20;
}
void g( int **p )
{
*p = malloc( sizeof( int ) );
**p = 30;
}
int main(void)
{
int x = 10;
printf( "x = %d\n", x );
f( &x );
printf( "x = %d\n", x );
int *px = &x;
printf( "*px = %d\n", *px );
g( &px );
printf( "*px = %d\n", *px );
free( px );
return 0;
}
Its output is
x = 10
x = 20
*px = 20
*px = 30

malloc fails when allocating pointer to struct of pointers - C [duplicate]

I need to do a simple thing, which I used to do many times in Java, but I'm stuck in C (pure C, not C++). The situation looks like this:
int *a;
void initArray( int *arr )
{
arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( a );
// a is NULL here! what to do?!
return 0;
}
I have some "initializing" function, which SHOULD assign a given pointer to some allocated data (doesn't matter). How should I give a pointer to a function in order to this pointer will be modified, and then can be used further in the code (after that function call returns)?
You need to adjust the *a pointer, this means you need to pass a pointer to the *a. You do that like this:
int *a;
void initArray( int **arr )
{
*arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( &a );
return 0;
}
You are assigning arr by-value inside initArray, so any change to the value of arr will be invisible to the outside world. You need to pass arr by pointer:
void initArray(int** arr) {
// perform null-check, etc.
*arr = malloc(SIZE*sizeof(int));
}
...
initArray(&a);

why do I need "static" for a char array in the function? [duplicate]

I am trying to create a new integer array which is derived from a string of characters. For example :
char x[] = "12334 23845 32084";
int y[] = { 12334, 23845, 32084 };
I am having trouble understanding how to return an array ( which I understand isn't possible ) from a function.
I originally tried :
/* Convert string of integers into int array. */
int * splitString( char string[], int n )
{
int newArray[n];
// CODE
return ( newArray );
}
int main( void )
{
int x[n] = splitString( string, n );
return ( 0 );
}
I later learned that you can not do this.
How do pointers work in regards to functions?
Thank you.
Typically, you require the caller to pass in the result array.
void splitString( const char string[], int result[], int n) {
//....
}
This is advantageous because the caller can allocate that memory wherever they want.
The problem is you're returning a pointer to something on the stack. You need to create your array on the heap, then free it when you're done:
int * splitString( char string[], int n )
{
int *newArray = malloc(sizeof(int) * n);
// CODE
return ( newArray );
}
int main( void )
{
int *x = splitString( string, n );
// use it
free(x);
return ( 0 );
}
int * splitString( char string[], int n )
{
int newArray[n];
return ( newArray );
}
This is very bad! The array newArray local to the function gets destroyed when the function returns. You'd be left out with a dangling pointer and using it would invoke undefined behaviour.
You can't return an array from a function. The best you can do is
int * splitString( char string[], int n )
{
int *newArray = malloc(n*sizeof(int)); // the array gets allocated on the heap rather than on the stack(1)
// Code
return ( newArray );
}
Don't forget to free the allocated memory.
(1) Note that the standard doesn't use/define the term stack or heap as such.
Rather than returning an array with return (newArray), you return a pointer to the first element of newArray.
The problem is that you're allocating the array the wrong way. If you instantiate it with int newArray[n], memory gets allocated on the current stack frame. That memory will be freed as soon as your function returns, and whatever was in the array will be garbage. Instead, do the following:
int *newArray = malloc(n * sizeof(int));
// etc.
return newArray
By using malloc, you allocate memory on the heap, where it will survive past the end of the current stack frame. Just remember to free(newArray) somewhere in your program when you're done.
You can wrap an array in a structure and then return an instance of the structure.
I'm mentioning this for completeness, it's not really something you'd want to do as it's ugly and there are better alternatives.
#include <stdio.h>
struct retval
{
int a[10];
};
struct retval test()
{
struct retval v = {{1, 5, 6}};
return v;
}
int main()
{
struct retval data = test();
printf("%d %d\n", data.a[1], data.a[2]);
}
The main issue i see is trying to return memory which you allocated on the stack, which becomes invalid once the function it was allocated in reutrns (in this case your splitString). What you can do is allocate the memory in the caller, and pass a pointer to the beginning of the array into the function
/* Convert string of integers into int array. */
void splitString(char string[], int *out_arr, int n )
{
// code that fills each cell of out_arr
}
int main( void )
{
int x[n];
splitString( string,(int *)x, n );
return ( 0 );
}
Of course it's possible.
This is the way I prefer:
int func(int** results)
Function returns number of elements in results. results is a pointer to an int array.

EXC_BAD_ACCESS when trying to access initialized array [duplicate]

I need to do a simple thing, which I used to do many times in Java, but I'm stuck in C (pure C, not C++). The situation looks like this:
int *a;
void initArray( int *arr )
{
arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( a );
// a is NULL here! what to do?!
return 0;
}
I have some "initializing" function, which SHOULD assign a given pointer to some allocated data (doesn't matter). How should I give a pointer to a function in order to this pointer will be modified, and then can be used further in the code (after that function call returns)?
You need to adjust the *a pointer, this means you need to pass a pointer to the *a. You do that like this:
int *a;
void initArray( int **arr )
{
*arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( &a );
return 0;
}
You are assigning arr by-value inside initArray, so any change to the value of arr will be invisible to the outside world. You need to pass arr by pointer:
void initArray(int** arr) {
// perform null-check, etc.
*arr = malloc(SIZE*sizeof(int));
}
...
initArray(&a);

C : double pointer passed as parameters comes back empty [duplicate]

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.

Resources