I have to write a function that will add an adress at the end of an array of pointers. Here is what I've done. I want to know if I did right and if not, please correct me.
#include <stdio.h>
#include <stdlib.h>
#define MAX 3
void add( int *array[MAX], int *addr)
{
array = realloc(array, 1*sizeof(int));
array[MAX+1] = addr;
}
int main()
{
int *addr = 4;
int *array[MAX] = {"1","2","3"};
add(array, addr);
int i;
for(i = 0; i<4;i++)
printf("%d ", array[i]);
return 0;
}
from the manual for realloc:
The realloc() function changes the size of the memory block pointed to
by ptr to size bytes. The contents will be unchanged in the range from
the start of the region up to the minimum of the old and new sizes. If
the new size is larger than the old size, the added memory will not be
initialized. If ptr is NULL, then the call is equivalent to
malloc(size), for all values of size; if size is equal to zero, and
ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr
is NULL, it must have been returned by an earlier call to malloc(),
calloc() or realloc(). If the area pointed to was moved, a free(ptr)
is done.
if its too long to read ill explain.
first of all you should use realloc after allocating memory ( using malloc for example ) and not after local declaration
second you're treating pointers to int ( int * ) as if they we're int. also shown as warning
examples:
int *addr = 4;
int *array[MAX] = {"1","2","3"};
array = realloc(array, 1*sizeof(int)); // here you're using sizeof( int )
another problem is reaching out of bound of array
array[MAX+1] = addr;
for an array with 3 spaces - you have array[ 0 ], array[ 1 ] and array[ 2 ].
in this line you're trying to reach the array[ 4 ] of an array ( that's suppose to be ) of size 4 --> out of bounds
my suggested code for this will be:
code edited
#include <stdio.h>
#include <stdlib.h>
#define MAX 3
void add( int **array[ MAX ], int *addr )
{
*array = realloc( *array, ( MAX + 1 ) * sizeof( int* ) );
(*array)[ MAX ] = addr;
}
int main()
{
int i;
int *addr;
int **array;
addr = &i;
array = malloc( MAX * sizeof ( int* ) );
for ( i = 1; i <= MAX; i++ ) {
array[ i - 1 ] = addr + 4 * i;
}
add( &array, addr );
for ( i = 0; i < MAX + 1; i++ ) {
printf( "%p ", array[ i ] );
}
return 0;
}
Related
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 3 months ago.
I've just started learning malloc() and realloc() and when testing them, I came across this issue with reallocating the size of an int array.
the program is supposed to make an array, initially of size two, but it's supposed to increase its size and add values to it ten times. However it doesn't increase its size and the output ends up being array = {0,1} when it should be array = {0,1,2,3,4,5,6,7,8,9}
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *array= malloc(sizeof(int)*2);
for (int x = 0; x < 10; x++) {
array = realloc(array, sizeof(int)*(2+x));
array[x] = x;
}
for (int i = 0; i<(sizeof(array)/sizeof(array[0])); i++) {
printf("%d\n",array[i]);
}
free(array);
}
could someone explain why it doesn't work?? I've tried looking for answers but none of this makes sense to me lol.
The expression
sizeof(array)/sizeof(array[0])
is equivalent to
sizeof( int * )/sizeof( int )
and yields either 2 or 1 depending on the used system.
Also the expression (2+x) in this statement
array = realloc(array, sizeof(int)*(2+x));
used in each iteration of the for loop does not make sense.
It seems you mean something like the following
enum { N = 10 };
size_t n = 2;
int *array = malloc( n * sizeof( int ) );
for ( int x = 0; x < N; x++ ) {
if ( n <= x )
{
n += 2;
array = realloc( array, n * sizeof( int ) );
}
array[x] = x;
}
for ( int i = 0; i < N; i++ ) {
printf("%d\n",array[i]);
}
free(array);
In general it is safer to use an intermediate pointer in the call pf realloc like for example
int *tmp = realloc( array, n * sizeof( int ) );
if ( tmp != NULL ) array = tmp;
Otherwise you can loose the allocated memory if the call of realloc will return a null pointer.
The problem is that sizeof(array) will just return the size of the pointer (8 bytes on a 64-bit system). You need to track the array size in another variable. For example...
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *array= malloc(sizeof(int));
int size;
for (size = 0; size < 10; size++) {
array = realloc(array, sizeof(int)*(1+size));
array[size] = size;
}
for (int i = 0; i<size; i++) {
printf("%d\n",array[i]);
}
printf("array size: %ld\n",size*sizeof(int));
free(array);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int a[4][5] =
{
{1,1,0,1,0},
{0,0,0,0,0},
{0,1,0,0,0},
{1,0,1,1,0}
};
int *ptr = &a[0][0];
for (; ptr < ptr+19; ptr++)
{
printf("%d ", *ptr);
}
return 0;
}
Why does this code not work? as far as i know 2D arrays are stored in row major order so like this:
[1,1,0,1,0]-[0,0,0,0,0]-[0,1,0,0,0]-[1,0,1,1,0]
So if i started at &a[0][0] and incremented it by 1 each time until it has been incremented to the last element why does this not work?
Aside from the danger caused from accessing data with pointers for different type, the loop condition is wrong.
ptr+19 moves with ptr and the condition ptr < ptr+19 will always be true (until overflow occurs).
Your code will be better if you retain the origin pointer and use that for stop condition.
int *ptr = &a[0][0];
int *start_ptr = ptr;
for (; ptr < start_ptr+19; ptr++)
{
printf("%d ", *ptr);
}
Alternative approach
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int a[4][5] =
{
{1,1,0,1,0},
{0,0,0,0,0},
{0,1,0,0,0},
{1,0,1,1,0}
};
int len = sizeof(a)/sizeof(a[0][0]) ;
int * ptr = &a[0][0] ;
while(len--)
{
printf("%d ", *ptr++);
}
return 0;
}
In this for loop
for (; ptr < ptr+19; ptr++)
the value of the expression ptr is always less than the value of the expression ptr + 19 (provided that there is no overflow in the last expression). Moreover the pointer ptr is incremented after each iteration of the loop.
So using this loop you will get access to memory outside the array a that results in undefined behavior.
What you need is the following for statement
for ( ; ptr < ( int * )a + sizeof( a ) / sizeof( **a ); ptr++)
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
int a[4][5] =
{
{1,1,0,1,0},
{0,0,0,0,0},
{0,1,0,0,0},
{1,0,1,1,0}
};
for ( int *ptr = ( int * )a; ptr < ( int * )a + sizeof( a ) / sizeof( **a ); ptr++ )
{
printf( "%d ", *ptr );
}
putchar( '\n' );
return 0;
}
The program output is
1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0
The following code gives me a terminated by signal SIGSEGV (Address boundary error):
void rec(int x, int *arr, int *size) {
if (x < 0) {
rec(-x, arr, size);
return;
}
arr = realloc(arr, sizeof(int) * ++(*size));
*(arr + (*size) - 1) = x % 10;
if (x % 10 != x)
rec(x / 10, arr, size);
}
int main() {
int *arr = malloc(sizeof(int));
int *size = malloc(sizeof(int));
*size = 0;
rec(20, arr, 0);
}
I already figured our that the arr counter in the main method won't hold the desired result, but I still can't understand why I'm getting an error.
Notice that you are passing NULL as third argument:
rec(20, arr, 0); // 0 is NULL
and you get a segfault dereferencing it:
arr = realloc(arr, sizeof(int) * ++(*size)); // here size is `NULL`
try with
rec(20, arr, size);
For starters these memory allocations
int *arr = malloc(sizeof(int));
int *size = malloc(sizeof(int));
does not make a sense. They are redundant.
You could just write
int *arr = NULL;
size_t size = 0;
Secondly the variable size is declared but not used because instead of the variable you passed the integer constant 0
rec(20, arr, 0);
So within the function rec
void rec(int x, int *arr, int *size);
the pointer size was initializer by the null pointer constant 0. That is size is a null pointer within the function and using a null pointer to access memory results in undefined behavior.
Also you should pass the pointer to the function by reference. Otherwise passing it to the function does not make a great sense because the pointer in main will not be changed.
The code in main could look like
int *arr = NULL;
size_t size = 0;
rec( 20, &arr, &size );
Pay attention to that you should free all the allocated memory when it will not be used any more.
Correspondingly the function should be declared like
void rec(int x, int **arr, size_t *size);
Use the type size_t instead of the type int because this unsigned integer type is the type of the second argument of the function realloc.
In general to get the result of realloc you should use an intermediate variable because the function can return a null pointer and the current pointer will be lost.
Also pay attention to that the call of the function is unsafe and can result in an infinite recursion due to this if statement
if (x < 0) {
rec(-x, arr, size);
return;
}
when the user passes to the function the value of x equal to INT_MIN.
Consider the following demonstrative program.
#include <stdio.h>
#include <limits.h>
int main(void)
{
int x = INT_MIN;
printf( "x = %d\n", x );
printf( "-x = %d\n", -x );
return 0;
}
Its output might look like
x = -2147483648
-x = -2147483648
As you can see negating the value of the variable x you get the same negative value. So maybe it is better to declare the first function parameter as having the type unsigned int.
Your function can look for example the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
int rec( unsigned int x, unsigned int **arr, size_t *size )
{
const unsigned int Base = 10;
unsigned int *tmp = realloc( *arr, sizeof( int ) * ++*size );
int success = tmp != NULL;
if ( success )
{
*arr = tmp;
*( *arr + *size - 1 ) = x % Base;
if ( x % Base != x )
{
success = rec( x / Base, arr, size );
}
}
return success;
}
int main(void)
{
unsigned int *arr = NULL;
size_t size = 0;
rec( 123456789, &arr, &size );
for ( size_t i = 0; i < size; i++ )
{
printf( "%u", *( arr + i ) );
}
putchar( '\n');
free( arr );
return 0;
}
The program output is
987654321
I have two structs:
struct first
{
int* array;
}
struct second
{
struct first* firsts;
} *SECOND;
Let's say somewhere I can get the address of one of struct first from SECOND->firsts by its index.
How could I get array of this struct? I've tried
SECOND->firsts[index]->array
but there is expression must have pointer-to-struct-or-union type error.
No malloc checks and no free - just to show the idea
struct first {
int* array; };
struct second {
struct first* firsts; } *SECOND;
#define NUMFIRSTS 50
#define ARRSIZE 50
int main() {
SECOND = malloc(sizeof(*SECOND));
SECOND -> firsts = malloc(NUMFIRSTS * sizeof(*SECOND -> firsts));
for(int f = 0; f < NUMFIRSTS; f++)
{
SECOND -> firsts[f].array = malloc(ARRSIZE * sizeof(*SECOND -> firsts[f].array));
}
//access
SECOND -> firsts[5].array[10] = 23;
}
Here you are.
#include <stdio.h>
#include <stdlib.h>
struct first
{
int* array;
};
struct second
{
struct first* firsts;
} *SECOND;
int main(void)
{
size_t n = 10;
struct first f = { NULL };
SECOND = malloc( sizeof( *SECOND ) );
SECOND->firsts = &f;
SECOND->firsts->array = malloc( n * sizeof( int ) );
for ( size_t i = 0; i < n; i++ )
{
SECOND->firsts->array[i] = ( int )i;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", SECOND->firsts->array[i] );
}
putchar( '\n' );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", f.array[i] );
}
putchar( '\n' );
// ...
// free all allocated memory
return 0;
}
the program output is
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
Pay attention to that as the pointer SECOND contains pointer to struct first f that in turn contains pointer to array then the both objects points to the same memory pointed to by the pointer array.
The array index operator [] has an implicit pointer dereference. So this expression:
SECOND->firsts[index]
Has type struct first, not struct first *, which means you can't use the -> operator on it. You need to instead use the member selector operator .:
SECOND->firsts[index].array
I would like to create a function which increase a given 2d dynamic int array with one row. I looked several website, guide, tutorial, but all is different, so I'm very confused now.
The 2d array has 2 fixed columns.
My code is here:
int length=1;
void arrayinc(int** array, int x0, int x1)
{
if (array == NULL)
malloc(array, sizeof(int[2]));
else
realloc(array, (++length)*sizeof(int[2]));
array[length-1][0]=x0;
array[length-1][1]=x1;
free(array);
}
int main()
{
int** array=NULL;
arrayinc(&array, 1, 2);
// I will do some stuff after the increase
}
I hope someone can help me, and explain how it really works!
Sorry for my english and bad malloc/realloc knowlage.
Function parameters are its local variables. So within the function you deal with a copy of the original argument.
At least the parameter shall be declared like
int*** array
If the number of columns is a compile-time constant then the function can be defined the following way.
#include <stdio.h>
#include <stdlib.h>
#define N 2
size_t arrayinc( int ( **array )[N], size_t n, int x0, int x1)
{
int ( *tmp )[N] = realloc( *array, ( n + 1 ) * sizeof( int[N] ) );
if ( tmp )
{
*array = tmp;
( *array )[n][0] = x0;
( *array )[n][1] = x1;
++n;
}
return n;
}
int main(void)
{
int ( *array )[N] = NULL;
size_t n = 0;
for ( size_t i = 0; i < 10; i++ )
{
n = arrayinc( &array, n, ( int )( 2 * i ), ( int )( 2 * i + 1 ) );
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d\t%d\n", array[i][0], array[i][1] );
}
free( array );
return 0;
}
The program output is
0 1
2 3
4 5
6 7
8 9
10 11
12 13
14 15
16 17
18 19