Dynamic array of array of int in C - c

How can an array of array of int be declared outside the main, then build inside the main once we know the length of the array of array we want to build, if one dimension is already known.
For example, if the array should be array[numberofargs][2], where the dimension 2 is already known but not numberofargs before execution of main.

One way is just to declare for example a pointer in a file scope like
int ( *array )[2] = NULL;
and then in one of functions allocate a memory for the array.
For example
#include <stdlib.h>
int (*array)[2] = NULL;
int main(void)
{
int numberofargs = 5;
array = malloc( sizeof( int[numberofargs][2] ) );
//...
free( array );
return 0;
}
Or the following way
#include <stdlib.h>
int **array = NULL;
int main(void)
{
int numberofargs = 5;
array = malloc( numberofargs * sizeof( *array ) );
for ( int i = 0; i < numberofargs; i++ )
{
array[i] = malloc( sizeof( *array[i] ) );
}
//...
for ( int i = 0; i < numberofargs; i++ )
{
free( array[i] );
}
free( array );
return 0;
}

Unfortunately, I do not know how to create an array where only the second dimension is known. What you can do is the following:
#include <stdlib.h>
#include <stdio.h>
#define SECOND_DIM 2
int *array;
// returns array[x][y]
int foo(int *array, int x, int y) {
return *(array+x*SECOND_DIM+y);
}
int main(int args, char *argv[]) {
if(!argv[0]) return 0;
array = malloc(args*SECOND_DIM*sizeof(int));
for(int i=0;i<args; i++) {
for(int j=0;j<SECOND_DIM; j++)
*(array+(i*SECOND_DIM)+j) = (i+1)*100+j;
}
printf("array[0][0]: %d\n", foo(array,0,0)); // array[0][0]
printf("array[0][1]: %d\n", foo(array,0,1)); // array[0][1]
free(array);
}

int (*array)[2] = malloc(sizeof(int[numberofargs][2]));
And then when you're finished with it:
free(array);

Related

How do I use a double pointer to manipulate an array in C?

I am running a simple program to print the first element value of an array using a double pointer:
#include <stdio.h>
int main()
{
int arr[3] = {1,2,3};
int **ptr;
*ptr = arr;
printf("%d\n", **ptr);
return 0;
}
But then I get a segmentation fault. What am I doing wrong?
The pointer ptr is not initialized and has an indeterminate value.
int **ptr;
So dereferencing it results in undefined behavior.
*ptr = arr;
You need an intermediate pointer. For example
int *p;
int **ptr = &p;
*ptr = arr;
Or you could allocate the intermediate pointer dynamically like
int **ptr = malloc( sizeof( int * ) );
*ptr = arr;
//...
free( ptr );
Here are two demonstrative programs.
#include <stdio.h>
int main( void )
{
int arr[3] = {1,2,3};
int *p;
int **ptr = &p;
*ptr = arr;
printf("%d\n", **ptr);
return 0;
}
and
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int arr[3] = {1,2,3};
int **ptr = malloc( sizeof( int * ) );
*ptr = arr;
printf("%d\n", **ptr);
free( ptr );
return 0;
}
The both programs have the output
1
If you need a pointer to the whole array then its declaration can look as it is shown in the demonstrative program below.
#include <stdio.h>
int main( void )
{
enum { N = 3 };
int arr[N] = { 1, 2, 3 };
int ( *ptr )[N] = &arr;
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", ( *ptr )[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2 3

C - Why does this function not reverse the array?

This function should reverse an array of vectors on the heap, but it doesn't work. It seems like the tmp_array also gets changed.
Output is:
13.700000 21.300000
13.700000 21.300000
Should be:
8.900000 31.700000
13.700000 21.300000
createVector creates a struct Vector with two double values x and y.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _Vector_
{
double x_;
double y_;
} Vector;
Vector *createVector(double x, double y)
{
Vector *vector = malloc((size_t)(sizeof(Vector)));
if (vector == NULL)
{
printf("Memory Error!\n");
return vector;
}
vector->x_ = x;
vector->y_ = y;
return vector;
}
void reverseVectorArray(Vector **vector_array, int length)
{
Vector **tmp_array = malloc(sizeof(Vector*)*length);
if(tmp_array == NULL)
{
printf("Memory Error!\n");
return;
}
memcpy(tmp_array, vector_array, sizeof(Vector*)*length);
int position = length - 1;
for(int i = 0; i<length; i++)
{
*(vector_array[position]) = *(tmp_array[i]);
position--;
}
free(tmp_array);
}
int main()
{
int length = 2;
Vector **vector_array = malloc(sizeof(Vector*) * 2);
vector_array[0] = createVector(13.7, 21.3);
vector_array[1] = createVector(8.9, 31.7);
reverseVectorArray(vector_array, length);
for(int i = 0; i<length; i++)
{
printf("%f ", vector_array[i]->x_);
printf("%f ", vector_array[i]->y_);
printf("\n");
}
return 0;
}
It seems you mean the following.
#include <stdio.h>
#include <stdlib.h>
typedef struct Vector
{
double x;
double y;
} Vector;
Vector * createVector( double x, double y )
{
Vector *vector = malloc( sizeof( Vector ) );
if ( vector )
{
vector->x = x;
vector->y = y;
}
return vector;
}
void reverseVectorArray( Vector **vector_array, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
Vector tmp = *vector_array[i];
*vector_array[i] = *vector_array[n - i - 1];
*vector_array[n - i - 1] = tmp;
}
}
int main( void )
{
size_t n = 2;
Vector **vector_array = malloc( n * sizeof( Vector * ) );
vector_array[0] = createVector( 13.7, 21.3 );
vector_array[1] = createVector( 8.9, 31.7 );
reverseVectorArray( vector_array, n );
for ( size_t i = 0; i < n; i++ )
{
printf( "%f ", vector_array[i]->x );
printf( "%f ", vector_array[i]->y );
putchar( '\n' );
}
return 0;
}
Take into account that you should append the program with a code that will free all allocated memory.
As for your code then for starters according to the C Standard the function main without parameters shall be declared like
int main( void )
If you are using the function memcpy then you need to include header <string.h>.
Instead of this declaration
Vector *vector = malloc((size_t)(sizeof(Vector*)));
^^^^^^^
you have to write
Vector *vector = malloc( sizeof( Vector ) );
^^^^^^
There is no need to allocate an auxiliary array to reverse the original array. Such an approach is inefficient.
The problem with your function reverseVectorArray is that it rewrites the values of the second half of the array with the values of the first half of the array. So it makes two halves of the array equal each other.

Return two pointers from a function in c

I know that you can return a pointer to the first element of an array in c by doing:
#include <stdlib.h>
#include <stdio.h>
int *my_func(void);
int main(void)
{
int *a;
int i;
a = my_func();
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, a[i]);
}
free(a);
return 0;
}
int *my_func(void)
{
int *array;
int i;
array = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
}
return array;
}
But if I wanted to return two pointers instead of just one, I tried:
#include <stdlib.h>
#include <stdio.h>
int *my_func(int *);
int main(void)
{
int *a;
int *b;
int i;
a = my_func(b);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, a[i]);
printf("b[%d] = %d\n", i, b[i]);
}
free(a);
free(b);
return 0;
}
int *my_func(int *array2)
{
int *array;
int i;
array = calloc(3, sizeof(int));
array2 = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
array2[i] = i;
}
return array;
}
But this seg faults on the printf for b. I ran it through valgrind and it says that there is an invalid read of size 4 at the printf for b, which means I'm doing something screwy with the b pointer. I was just wondering what the best way to "return" a second pointer to an array was in c? I'm asking because I would like to do it this way rather than use a global variable (I'm not opposed to them, as they are useful at times, I just prefer not to use them if possible). The other questions I've seen on this site used statically allocated arrays, but I haven't yet stumbled across a question that was using dynamic allocation. Thanks in advance!
I can think of three (and a half) simple ways to return multiple items of any kind from a C-function. The ways are described below. It looks like a lot of text, but this answer is mostly code, so read on:
Pass in an output argument as you have done, but do it correctly. You have to allocate space for an int * in main() and then pass the pointer to that to my_func.
In main():
a = my_func(&b);
my_func() becomes:
int *my_func(int **array2)
{
int *array;
int i;
array = calloc(3, sizeof(int));
*array2 = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
(*array2)[i] = i;
}
return array;
}
Make your function allocate array of two pointers to the int arrays you are trying to allocate. This will require an additional allocation of two int pointers, but may be worth the trouble.
main() then becomes:
int main(void)
{
int **ab;
int i;
ab = my_func(b);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab[0][i]);
printf("b[%d] = %d\n", i, ab[1][i]);
}
free(ab[0]);
free(ab[1]);
free(ab);
return 0;
}
my_func() then becomes:
int **my_func(void)
{
int **arrays;
int i, j;
arrays = calloc(2, sizeof(int *));
arrays[0] = calloc(3, sizeof(int));
arrays[1] = calloc(3, sizeof(int));
for(j = 0; j < 2; j++)
{
for(i = 0; i < 3; i++)
{
arrays[j][i] = i;
}
}
return arrays;
}
Return a structure or structure pointer. You will need to define the structure, and decide whether you want to return the structure itself, a newly allocated pointer to it, or pass it in as a pointer and have my_func() fill it in for you.
The structure definition would look something like this:
struct x
{
int *a;
int *b;
}
You would then rephrase your current functions as one of the following three options:
Direct passing of structure (not recommended for general use):
int main(void)
{
struct x ab;
int i;
ab = my_func();
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab.a[i]);
printf("b[%d] = %d\n", i, ab.b[i]);
}
free(ab.a);
free(ab.b);
return 0;
}
struct x my_func(void)
{
struct x ab;
int i;
ab.a = calloc(3, sizeof(int));
ab.b = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
ab.a[i] = i;
ab.b[i] = i;
}
return ab;
}
Return a pointer to a dynamically allocated structure (this is a pretty good option in general):
int main(void)
{
struct x *ab;
int i;
ab = my_func();
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab->a[i]);
printf("b[%d] = %d\n", i, ab->b[i]);
}
free(ab->a);
free(ab->b);
free(ab);
return 0;
}
struct x *my_func(void)
{
struct x *ab;
int i;
ab = malloc(sizeof(struct x));
ab->a = calloc(3, sizeof(int));
ab->b = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
ab->a[i] = i;
ab->b[i] = i;
}
return ab;
}
Allocate the structure in main() and fill it in in my_func via a passed-in pointer. This option is often used in a way where my_func would allocate the structure if you pass in a NULL pointer, otherwise it would return whatever you passed in. The version of my_func shown here has no return value for simplicity:
int main(void)
{
struct x ab;
int i;
my_func(&ab);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, ab.a[i]);
printf("b[%d] = %d\n", i, ab.b[i]);
}
free(ab.a);
free(ab.b);
return 0;
}
void my_func(struct x *ab)
{
int i;
ab->a = calloc(3, sizeof(int));
ab->b = calloc(3, sizeof(int));
for(i = 0; i < 3; i++)
{
ab->a[i] = i;
ab->b[i] = i;
}
return;
}
For all the examples shown here, don't forget to update the declaration of my_func at the top of the file, although I am sure any reasonable compiler will remind you if you forget.
Keep in mind also that these are just three options I pulled out of my brain at a moments notice. While they are likely to cover 99% of any use cases you may come up against any time soon, there are (probably lots of) other options out there.
Function parameters are its local variables. Functions deal with copies of values of the supplied arguments.
You can imagine your function definition and its call the following way
a = my_func(b);
int *my_func( /* int *array2 */ )
{
int *array2 = b;
//...
}
So any changes of the local variable array2 inside the function do not influence on the original argument b.
For such a function definition you have to pass the argument by reference that is the function should be declared like
int *my_func( int **array2 );
^^
There are many ways to implement the function. You could define a structure of two pointers as for example
struct Pair
{
int *a;
int *b;
};
and use it as the return type of the function
struct Pair my_func( void );
Another approach is to pass to the function an array of pointers to the original pointers.
The function can look as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
size_t multiple_alloc( int ** a[], size_t n, size_t m )
{
for ( size_t i = 0; i < n; i++ ) *a[i] = NULL;
size_t k = 0;
for ( ; k < n && ( *a[k] = malloc( m * sizeof( int ) ) ) != NULL; k++ )
{
for ( size_t i = 0; i < m; i++ ) ( *a[k] )[i] = i;
}
return k;
}
#define N 2
#define M 3
int main(void)
{
int *a;
int *b;
multiple_alloc( ( int ** [] ) { &a, &b }, N, M );
if ( a )
{
for ( size_t i = 0; i < M; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
}
if ( b )
{
for ( size_t i = 0; i < M; i++ ) printf( "%d ", b[i] );
putchar( '\n' );
}
free( a );
free( b );
return 0;
}
The program output is
0 1 2
0 1 2
#include <stdlib.h>
#include <stdio.h>
int *my_func(int **);
int main(void)
{
int *a;
int *b;
int i;
b=(int *)malloc(sizeof(int));
a = my_func(&b);
for(i = 0; i < 3; i++)
{
printf("a[%d] = %d\n", i, a[i]);
printf("b[%d] = %d\n", i, b[i]);
}
free(a);
free(b);
return 0;
}
int *my_func(int **array2)
{
int *array;
int i;
array = calloc(3, sizeof(int));
*array2 =calloc(3,sizeof(int));
for(i = 0; i < 3; i++)
{
array[i] = i;
*((*array2)+i)=i;//or (*array2)[i]
}
return array;
}
Pass the pointer by reference. Because its the same logic as, to manipulate an integer block you need to pass a pointer to it. Similarly, to manipulate a pointer, you will have to pass a pointer to it(i.e. pointer to pointer).

reallocation of 2d arrays in c

I want to reallocate a 2d array, so that the arrays in the second array become bigger, so the things I want to store are bigger than the arrays I want to store them in and I want to make the arrays bigger. The problem is that I do not really know how to do this. I got it to compile without errors, but in Valgrind I saw a lot of memory errors, so I do something wrong. I saw a previous question about this here but I do not really understand it, so any help and explanation on how to do this would be greatly appreciated.
I have this so far.
int **create2darray(int a, int b) {
int i;
int **array;
array = malloc(a * sizeof(int *));
assert(array != NULL);
for (i = 0; i < a; i++) {
array[i] = calloc(b, sizeof(int));
assert(array[i] != NULL);
}
return array;
}
int **reallocArray(int **array, int size, int i) {
int i;
int **safe_array;
safe_array = realloc(*array ,2 * size);
assert(safe_array != NULL);
array = safe_array;
return array;
}
void free2DArray(int **array, int m) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
}
int main(int argv, char *argc[]) {
int i;
int size;
int **testArray = create2darray(1, 10);
size = 10;
for(i = 0; i < size; i++) {
testArray[0][i] = 2;
}
testArray[0] = reallocArray(testArray, size, 0);
size = 2 * size;
for(i = 9; i < size; i++) {
testArray[0][i] = 3;
}
for(i = 0; i < size; i++) {
printf("%d", testArray[0][i]);
free2DArray(testArray, size);
}
return 0;
}
You need a function reallocArray which realaoctes the outer array and all the inner arrays too.
Adapt youre code like this:
#include <malloc.h>
int **reallocArray( int **array, int oldSizeA, int newSizeA, int newSizeB )
{
// realloc the array of pointers ( allocates new memory if array == NULL )
int **safe_array = realloc( array, newSizeA * sizeof( int* ) );
assert(safe_array != NULL);
if ( safe_array == NULL )
return array;
array = safe_array;
// realloc the inner arrays of int ( allocates new memory if i >= oldSizeA )
for ( int i = 0; i < newSizeA; i ++ )
{
int *temp = NULL; // allocate new memory if i >= oldSizeA
if ( i < oldSizeA )
temp = array[i]; // reallocate array[i] if i < oldSizeA
temp = realloc( temp, newSizeB * sizeof( int ) );
assert( temp != NULL );
if ( temp == NULL )
return array;
array[i] = temp;
}
return array;
}
Use function reallocArray in your function create2darray to create your array. If the input paramter of ralloc is NULL, then new dynamic memory is allocated.
int **create2darray( int sizeA, int sizeB )
{
return reallocArray( NULL, 0, sizeA, sizeB );
}
First you have to free the inner arrays of int in a loop, then you have to free the array of pointers:
void free2DArray( int **array, int sizeA )
{
for (int i = 0; i < sizeA; i ++)
free( array[i] );
free( array );
}
int main( int argv, char *argc[] ){
int sizeA = 1;
int sizeB = 10;
int **testArray = create2darray( sizeA, sizeB );
for ( int i = 0; i < sizeB; i++ ) {
testArray[0][i] = 2;
}
int oldSizeA = sizeA;
int oldSizeB = sizeB;
sizeB = 2*sizeB;
testArray = reallocArray( testArray, oldSizeA, sizeA, sizeB );
for( int i = oldSizeB; i < sizeB; i++ ) {
testArray[0][i] = 3;
}
for( int i = 0; i < sizeB; i++ ) {
printf("%d", testArray[0][i]);
}
free2DArray(testArray, sizeA );
return 0;
}
In Free2DArray(), you free() the individual arrays of integers, but not the "outer" dimension of the array which holds the integer pointers.
You could add another call to free() after the loop to take care of that.
In main():
for(i = 0; i <size; i++) {
printf("%d", testArray[0][i]);
free2DArray(testArray, size);
}
you will end up free()-ing the (inner) integer arrays multiple times.
The call to free2DArray() should be outside the loop.

Modifying a array in a function in C

#include <stdio.h>
#include <stdlib.h>
void array_tester(int *array);
int main(int argc,char *argv[])
{
int test[] = {1,1,1,1};
int print;
for(print = 0; print < sizeof(test) / sizeof(int); print++)
{
printf("%d\n",test[print] );
}
array_tester(test);
for(print = 0;print < sizeof(test)/sizeof(int);print++)
{
printf("%d\n",test[print] );
}
return EXIT_SUCCESS;
}
void array_tester(int array[])
{
int i ;
for(i = 0; i < sizeof(array) / sizeof(int); i++)
{
array[i] = i;
}
}
The problem is I want to modify the the array in the array_tester function but I'm unable to do so. What do I use inside sizeof()?
You have to manually pass the information about the size of the array.
void array_tester( int* array , int size ) ;
And then call it:
array_tester( test , sizeof(test)/sizeof(*test) ) ;
The reason behind this is that array passed to a function will decay to a pointer and the sizeof will return the size of pointer not the original array.

Resources