Malloc and Realloc for Int Array [duplicate] - c

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

Related

how to filter an array and overwrite that

I need to filter some specific elements from an array. I write the code which work perfectly:
#include <stdio.h>
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
int main (int argc, char *argv[]) {
// our initial array
int x[] = {1,2,-3,4,5};
// initialize filtered_array with pointer
int *filtered;
int upper_bound = 4, lower_bound = 1, i, j=0, total = -1,result;
size_t n = NELEMS(x);
printf("size of the main array: %d\n",n);
// check which element satisfy the condition and count them
for (i=0;i<n;++i)
{
total = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? total+1 : total;
};
// allocate array size for filtered array
filtered = (int*) calloc(total,sizeof(int));
for (i=0;i<n;++i)
{
// filter element from main array and store them in filtered array
result = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? 1 : 0;
if(result) {
filtered[j] = x[i];
++j;
};
};
for (i = 0; i<total+1; ++i){
printf("%d ",filtered[i]);
};
return 0;
}
But can I avoid to create a new array like I used filtered and dynamically do this for the main array by some overwrite trick?
For starters your program is incorrect.
Firstly you need to include the header <stdlib.h>
#include <stdlib.h>
Secondly, initially total is set to -1
total = -1
So if the original array contains only one element that satisfies the condition then total will be equal to 0 due to this statement
total = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? total+1 : total;
As a result this statement
filtered = (int*) calloc(total,sizeof(int));
is trying to allocate a memory with the size equal to 0. If the memory will be allocated (it is implementation defined) then you may not write anything in this memory. Otherwise the program will have undefined behavior.
In any case you are counting elements that satisfy the condition incorrectly and hence allocating a block of memory of an incorrect size.
Also there is no sense to insert a null statement after compound statements as you are doing
for (i=0;i<n;++i)
{
//...
};
^^^
Remove such redundant semicolons.
And you are using an incorrect conversion specifier in this call of printf.
printf("size of the main array: %d\n",n);
^^^
You have to write
printf("size of the main array: %zu\n",n);
^^^
As for your question
But can I avoid to create a new array like I used filtered and
dynamically do this for the main array by some overwrite trick?
then what you need is to change the array in place and to track the number of actual elements that satisfy the condition.
For example
int x[] = {1,2,-3,4,5};
// initialize filtered_array with pointer
size_t n = NELEMS(x);
int upper_bound = 4, lower_bound = 1;
printf( "size of the main array: %zu\n", n );
size_t m = 0;
for ( size_t i = 0; i < n; ++i )
{
if ( x[i] >= lower_bound) && x[i] <= upper_bound )
{
if ( m != i )
{
x[m] = x[i];
}
++m;
}
}
for ( size_t i = 0; i < m; ++i )
{
printf( "%d ", x[i] );
}
putchar( '\n' );
If you need to reallocate the original array according to the number of elements that satisfy the condition then the code can look for example the following way
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//...
size_t n = 5;
int *x = malloc( n * sizeof( int ) );
memcpy( x, ( int[] ){ 1, 2, -3, 4, 5 }, n * sizeof( int ) );
int upper_bound = 4, lower_bound = 1;
printf( "size of the main array: %zu\n", n );
size_t m = 0;
for ( size_t i = 0; i < n; ++i )
{
if ( x[i] >= lower_bound) && x[i] <= upper_bound )
{
if ( m != i )
{
x[m] = x[i];
}
++m;
}
}
if ( m != n )
{
int *tmp = realloc( x, m * sizeof( int ) );
if ( tmp != NULL )
{
x = tmp;
for ( size_t i = 0; i < m; ++i )
{
printf( "%d ", x[i] );
}
putchar( '\n' );
}
}
free( x );
What you are looking for is called modification (in this case filtering) in place.
That's even pretty simple:
int* filter(int* begin, int* end)
{
int* pos = begin; // start at the beginning of the array
for(; begin != end; ++begin)
{
if(*begin != 0) // your appropriate condition!
// this one filters out all zero values...
{
*pos++ = *begin; // copy current element to retain into
// first position not yet used
// (pos always points to one element past
// the last one retained!)
}
}
return pos; // as above, points to one past the last element retained
}
The return value is important to know how many elements remained.
If you prefer, you can instead write an index-based variant avoiding pointer arithmetics...
The basic idea about the filtering algorithm is that you just copy the elements towards the front, overwriting those values that either are filtered away or have already been copied.
Edit: Additional explanations:
begin and end pointers are to be passed as pointer to first element of the array and pointer to one past the array (typical C++ semantics when iterating over C++ STL containers, though these come with their own iterator types instead of pointers...).
So you'd call the function like:
int array[N];
int* newEnd = filter(array, array + sizeof(array)/sizeof(*array));
This is typical C++ semantics when iterating over STL containers (though these come with their specific iterator types instead of poitners).
If you don't like:
size_t filter(size_t length, int array[length]) // note: length as array subscript
// is ignored anyway...
{
int* pos = array;
int* begin = array;
int* end = array + length;
// now following the identical loop as above
return pos - array; // pointer difference; if pos points one past the last
// element you get the *number* of elements retained
}
About *pos++ = *begin: That's nothing special and any good C book should explain that nicely to you...
It copies the value begin points to to the address pos points to and increments pos afterwards.
An indexing loop doing the same might look as follows:
size_t pos = 0;
for(size_t i = 0; i < length; ++i)
{
array[pos++] = array[i]
}
return pos;

What is the meaning of this pointer to pointer statement in C? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
int **arr = (int **)malloc(r * sizeof(int *));
how should i interpret the meaning of the above C code ?
The call to malloc() in:
int **arr = (int **)malloc(r * sizeof(int *));
allocates space for r pointers to int, and returns a void * pointing to the allocation. This pointer is then cast to int ** and assigned to arr, which is a pointer to a pointer to int. Thus arr points to the first element of the allocated region, which is a pointer to int. Such code may be used in creating a "jagged" array, where each row of the array is allocated separately; this means that the allocations may not be contiguous in memory, so this would not be a true 2d array. See Correctly allocating multi-dimensional arrays to read more about this.
The above is considered bad style, though. Most importantly, using explicit types as arguments of the sizeof operator should be avoided when possible:
int **arr = (int **)malloc(r * sizeof *arr);
This is less error-prone, and easier to maintain if the type of arr changes at some point in the life of the code.
Further, there is no need to cast the result of malloc() in C, so this cast is superfluous and only serves to clutter the code:
int **arr = malloc(r * sizeof *arr);
As a final refinement, I prefer to place the sizeof expression first in such cases:
int **arr = malloc(sizeof *arr * r);
This is a useless change in the particular case above, but when there is an additional multiplication, e.g.:
int **arr = malloc(sizeof *arr * r * n);
this guarantees that the arithmetic is carried out with a type at least as wide as size_t, reducing the risk of integer overflow (signed integer overflow causes undefined behavior in C), and may reduce the risk of unsigned integer wrap-around (well-defined, but possibly unexpected or unwelcome).
This
int **arr = (int **)malloc(r * sizeof(int *));
is a dynamic allocation of an array of the type int * [r] that is an array of r elements that have the type int *.
To make the declaration more clear consider the following simple program
#include <stdio.h>
int main(void)
{
char * s[] = { "Hello", " ", "user292174" };
const size_t N = sizeof( s ) / sizeof( *s );
char **p = s;
for ( size_t i = 0; i < N; i++ ) printf( "%s", p[i] );
putchar( '\n' );
return 0;
}
Its output is
Hello user292174
Here in the program instead of the type int there is used type char for simplicity.
Array designators in expressions with rare exceptions are converted to pointers to their first elements.
So as the type of the array s is char * then a pointer to first element of the array s will have the type char **.
In the case of the original declaration from the question then there is allocated dynamically an extent of memory that is interpreted as an array of elements of the type int *. And the starting address of the extent where the first lement of the implyed array will be exist is assigned to the pointer. So the pointer shall have the type int **.
int **arr = (int **)malloc(r * sizeof(int *));
Usually such allocations are used to simulate a two-dimensional array when the number of rows and columns of the array are calculated at run-time.
For example
#include <stdio.h>
#include<stdlib.h>
int main(void)
{
size_t r = 2;
size_t c = 3;
int **arr = (int **)malloc( r * sizeof( int * ) );
for ( size_t i = 0; i < r; i++ )
{
arr[i] = malloc( c * sizeof( int ) );
}
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
arr[i][j] = c * i + j;
}
}
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
printf( "%d ", arr[i][j] );
}
putchar( '\n' );
}
for ( size_t i = 0; i < r; i++ )
{
free( arr[i] );
}
free( arr );
return 0;
}
The program output is
0 1 2
3 4 5
If the compiler supports variable length arrays then a two dimensional array can be allocated at once. For example
#include <stdio.h>
#include<stdlib.h>
int main(void)
{
size_t r = 2;
size_t c = 3;
int ( *arr )[c] = (int **)malloc( sizeof( int[r][c] ) );
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
arr[i][j] = c * i + j;
}
}
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
printf( "%d ", arr[i][j] );
}
putchar( '\n' );
}
free( arr );
return 0;
}
The porgram output is the same as shown above.

Two dimensional array malloc in C ---> error?

I am trying to make two dimensional array function, but somehow it is not working. The code here:
#include <stdio.h>
#include <stdlib.h>
int **multiTable (unsigned int xs, unsigned in ys)
{
unsigned int i, j;
int **table = int(**)malloc(xs * ys * sizeof(int*));
for(i = 0; i < ys; i++)
{
for(j = 0; j < xs; j++)
{
table[i][j] = j * i;
}
}
free(**table);
return table;
}
So first of all, should I also add inside the malloc the row (xs)? Or should it work, if I work only with the columns? --> like this:
int **table = int(**)malloc(ys * sizeof(int*));
That is not going to work as an array of pointers int **table is not contiguous and it is not equivalent to a 2d array table[a][b].
You can however use a pointer to an array if you want to use a single malloc.
int (*table)[xs] = malloc( ys * sizeof(*table));
for( int i = 0; i < ys; i++)
{
for( int j = 0; j < xs; j++)
{
table[i][j] = i;
}
}
free( table ) ;
And do not return table after you free it as your return call does.
It seems you mean the following
int ** multiTable( unsigned int xs, unsigned int ys )
{
unsigned int i, j;
int **table = malloc( ys * sizeof( int * ) );
for ( i = 0; i < ys; i++ )
{
table[i] = malloc( xs * sizeof( int ) );
for ( j = 0; j < xs; j++ )
{
table[i][j] = j * i;
}
}
return table;
}
'table' is a 2-D pointer. First understand what is a 2D pointer. A pointer is a special type of variable that is used to store the address of another variable. So a 2D pointer is a special variable that is again used to store the address of a pointer variable.
Now imagine that you have a single array of pointers(collection of base address of different 1-D array), that will store the base address of many 1-D arrays.
To dynamically allocate memory to this array of pointers you need the statement
table=(int**)malloc(sizeof(int*)*xs);
Now you have an array with 'xs' number of elements, and you can access each element by table[0], table[1], table[2]..and so on..., but none of these arrays is allocated memory. So you need to allocate memory to each of the array individually using a loop like this:
for(i=0;i<xs;i++)
table[i]=(int*)malloc(sizeof(int)*ys);
So your over-all program becomes:
int **table; // table is a 2D pointer
table=(int**)malloc(sizeof(int*)*xs);
for(i=0;i<xs;i++)
table[i]=(int*)malloc(sizeof(int)*ys);
for(i = 0; i < ys; i++)
{
for(j = 0; j < xs; j++)
{
table[i][j] = j * i;
}
}
return table;
You don't need to free the array before returning it. Doing so will make your pointer 'table' a dangling pointer that is still referring to a memory that is no longer allocated, so just return 'table' without the statement:
free(table);
The above statement will lead to a dangling memory that has no access point, ans so is useless. This is a memory leakage problem that arises when memory gets accumulated, and this memory is no more accessible through your program and could not be relocated for other purpose, such a memory is called dangling memory.

Strange output from Counting Sort in C

I have the following Counting Sort function
/*
*File: countingSort.c
*Description: A counting sort subroutine. Takes as input an array of integers.
* an array length and a range. All values in the input array must fall within [0, range].
* Takes O(range + arrayLen) time and O(range + arrayLen) extra space
*
*/
#include "countingSort.h"
int* countingSort(int unsorted[], int arrayLen, int range) {
int store[range + 1];
int sorted[arrayLen];
for ( int i = 0; i <= range; i++ ) {
store[i] = 0;
}
for ( int i = 0; i < arrayLen; i++ ) {
sorted[i] = 0;
}
for ( int j = 0; j < arrayLen; j++ ) {
store[unsorted[j]] ++;
}
for ( int i = 1; i <= range; i++ ) {
store[i] += store[i-1];
}
for( int j = arrayLen - 1; j >= 0; j-- ) {
sorted[store[unsorted[j]]] = unsorted[j];
store[unsorted[j]] --;
}
return sorted;
}
The function is giving me really strange output. The output is nothing like the input most of the times but sometimes it just works.
Why is this happening?
I am calling it from another file called cSortTest.c.
That file looks like this
/*
*File: cSortTest.c
*Description: Tests countingSort.c
*
*/
#include <stdio.h>
#include "countingSort.h"
int main() {
int data[8] = { 2, 1, 9, 4, 4, 56, 90, 3 };
int* p;
p = countingSort(data, 8, 90);
for ( int i = 0; i < 8; i++ ) {
printf("%d Element: %d\n", i, *(p+i) );
}
}
You are returning a local array variable. This variable is destroyed when the function exits, making the address to it no longer safe or valid to access. In fact accessing it will give you what is called undefined behavior, which explains why it sometimes appears to "work".
This is a classic beginner's mistake in C. You must either have the caller pass in the desired destination array, or use malloc() to allocate "persistent" heap memory and return that:
int* countingSort(int unsorted[], int arrayLen, int range) {
int *sorted = malloc(arrayLen * sizeof *sorted );
if (sorted== NULL)
return NULL;
/* rest of sorting */
return sorted;
}
The arrayLen * sizeof *sorted expression computes the number of bytes required for the allocation. There's no need to use calloc() which clears the memory; you're going to overwrite each element so clearing it is just wasted effort.

Memory allocation in my simple game [duplicate]

This question already has answers here:
Using malloc for allocation of multi-dimensional arrays with different row lengths
(8 answers)
Closed 9 years ago.
I'm writing the minesweeper game in C. I want be able to play games with different minefields with different sizes and number of mines
I've created such structures to describe my data:
typedef struct t_Place Place;
struct t_Place{
unsigned numberOfMinesNear;
int mine;
int state;
};
typedef struct t_Minefield Minefield;
struct t_Minefield{
int xSize;
int ySize;
unsigned minesNumber;
Place **places;
};
So, now I'm trying to initialize my minefield. I do the following:
void makeGame(Minefield *minefield, unsigned x, unsigned y, unsigned mines){
int i, j;
minefield->places = malloc(x * y * sizeof(Place));
for(i = 0; i < x; i++)
for(j = 0; j < y; j++){
minefield->places[i][j].mine = EMPTY;
minefield->places[i][j].state = HIDDEN;
minefield->places[i][j].numberOfMinesNear = 0;
}
minefield->xSize = x;
minefield->ySize = y;
unsigned minesToPlace = mines;
srand(time(NULL));
while(minesToPlace > 0){
i = rand() % x;
j = rand() % y;
if(minefield->places[i][j].mine)
continue;
minefield->places[i][j].mine = MINE;
minesToPlace--;
}
minefield->minesNumber = mines;
// here will be call of play(minefield) function to start the game
}
int main(){
Minefield *gameField = (Minefield *) malloc(sizeof(Minefield));
makeGame(gameField, DEFAULT_X, DEFAULT_Y, DEFAULT_MINES);
// DEFAULT_X = DEFAULT_Y = DEFAULT_MINES = 10
free(gameField);
return 0;
}
I'm getting segfault at first line of code in makeGame function. What i'm doing wrong? I want allocate memory for my minefield dynamically, not statically.
minefield->places = malloc(x * y * sizeof(Place));
The above memory allocation might be the source of the problem , places is a two star pointer , so there must be two malloc() calls , one to allocate the row number **place pointers , and then another malloc() , to allocate column number of *place pointers of type place.
Here is a SSCCE of allocating/initializing a two star pointer contained inside a structure.
#include <stdio.h>
#include <stdlib.h>
#define ROW_SZ 5
#define COL_SZ 25
typedef struct demo{
char **str;
}demo;
int main()
{
demo *d = malloc( sizeof(demo) );
d->str = malloc(ROW_SZ * sizeof(char*) ); //d->str is assigned char**
for ( i = 0; i < ROW_SZ; i++ )
d->str[i] = malloc(COL_SZ * sizeof(char) ); //d-str[i] is assigned char*
// code here to use d->str[ROW_SZ][COL_SZ]
for ( i = 0; i < ROW_SZ; i++ )
free(d->str[i]);
free(d->str);
free(d);
return 0;
}
This is how I usually see 2D arrays allocated:
minefield->places = malloc(x * sizeof(Place *));
for(i = 0; i < x; i++)
{
minefield->places[i] = malloc(x * sizeof(Place));
}
Try this and see if it makes you segfault vanish.

Resources