pointer of a pointer and memory allocation - c

If I have int **array and want to place a series of numbers in it (I don't know its size), 5 3 4 0 or 9 1 5 8 3 0 as an example. As far as I know I should be using malloc
So I did something like this
int **array;
int n = 1, inp = 0;
while(n){ // scan till the input is 0
scanf("%d", &n);
array = (int**)malloc(sizeof(int*)*(inp+1)); //since inp start at 0
array[inp] = &n; //is this even correct?
inp++;
}
My first question is: Will this method (the loop) upgrade/expand the size of the array or is what I am doing a waste of memory?
The second question is how can I print/edit the values of this array?
EDIT:
From your answers I have came up with the following.
int **array;
int n = 1, inp = 0;
array = (int**)malloc(sizeof(int*));
while(n){
scanf("%d", &n);
realloc( array, sizeof((int*)(inp+1)));
array[inp] = n;
inp++;
}
Is this the correct way to do it?
Note* I am aware that it does not have to be a pointer of a pointer, but I need it to be for something else later on.

You code is wrong for at least these reasons.
1) You keep doing malloc to array and thereby loose previously malloced blocks. The function to use is realloc when extending the size of dynamic memory.
2) You store the address of n instead of the value of n
Besides that it seems strange to use a double pointer. Why not do like:
int *array = NULL;
int n = 1, inp = 0;
while(n){ // scan till the input is 0
scanf("%d", &n);
array = realloc(array, sizeof(int)*(inp+1));
array[inp] = n;
inp++;
}
EDIT after OPs update
If you really want to use a double pointer (i.e. int **array;), you need to allocate memory in two levels.
That could look like:
int **array = malloc(sizeof *array);
*array = NULL;
int n = 1, inp = 0;
while(n){ // scan till the input is 0
scanf("%d", &n);
*array = realloc(*array, sizeof(int)*(inp+1));
(*array)[inp] = n;
inp++;
}

What you're doing in your code is allocating progressively larger areas of memory and saving the input value in the last position of each new area, while losing the pointers to the previously allocated areas. A commom and efficient solution for what you want (which is used in C++'s vectors, I believe) is to allocate some minimum amount of space, then check at each iteration if you are on the verge of exceeding it. In case you are, reallocate the area doubling the space. Something like this:
int i = 0; //iterator
int s = 1; //array size
int n; //input (use do-while so you don't have to worry about initial value)
//it doesn't have to be bidimensional for a single series
int * array = (int *) malloc(sizeof(int) * s);
do
{
if(i == s)
{
s *= 2;
array = (int *) realloc(array, sizeof(int) * s);
}
scanf("%d", &n);
array[i++] = n; //assign with the value, not with the address
}
while(n)
UPDATE: if you really need to use **int, do it like this:
int n, i = 0, s = 1;
int ** array = (int **) malloc(sizeof(int*) * s);
do
{
if(i == s)
{
s *= 2;
array = (int **) realloc(array, sizeof(int *) * s);
}
scanf("%d", &n);
array[i] = (int *) malloc(sizeof(int));
array[i][0] = n;
++i;
}
while(n)

Related

Why the scan stopped working (using memory allocation)?

I've done this code to read an array, it works properly in the small tests (3x3), however i need it to read a 15x15 one. After 150 scans it has stopped working, returned 3221225477 and closed.
What is happening? How to fix it?
int ** ler(){
FILE *a;
a = fopen("matriz.txt", "r");
int **N;
int b, c, d;
N = malloc(15 * sizeof(int));
for (b = 0; b < 15; b++){
N[b] = malloc(15 * sizeof(int));
}
for (b = 0; b < 15; b++){
for (c = 0; c < 15; c++){
fscanf(a, "%i", &d);
N[b][c] = d;
}
}
return N;
}
At least this problem:
Wrong size allocation
int **N; // vvvvvvvvvvv This is the size of an int
//N = malloc(15 * sizeof(int));
N = malloc(15 * sizeof *N);
// ^^^^^^^^^ The size of a pointer is needed here
With OP's code, when the size of an int < size of an int *, the allocation is undersized.
Avoid that mistake and code with *N rather than attempting to match the type.
// Nice idiom
ptr = malloc(sizeof *ptr * n);
// ^^^^^^^^^^^ The right size regardless of what `ptr` pointers to.
Call fclose(a) when done reading.

Can someone explain me what is going on in this statement?

Basically i understand pointers. But when it comes to dynamic allocation for matrices which also involve pointers, i'm getting lost in the process. I wanna know how can i translate this segment of code in order to understand it.
(*a)[i] = (int*)malloc((*m) * sizeof(int));
The function for reading the matrix looks like this:
void reading(int *n, int *m, int ***a) {
int i, j;
printf("n=");
scanf("%d", &*n);
printf("m=");
scanf("%d", &*m);
(*a) = (int**)malloc((*n) * sizeof(int*));
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
}
And also what is the meaning of ***a in the declaration. I was told at college that te first asterisk stands for dynamic allocation and the other two's from the fact that is a matrix involved. For vectors dynamic allocation is **v and so on... but i can't naturally explain it in my mind in order understand what is happening in it.
First let me answer your question about this specific line:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
What this is doing is allocating an array of exactly *m integers and saving a pointer to it into the array *a of pointers to int, which was previously allocated as:
(*a) = (int**)malloc((*n) * sizeof(int*));
Now, if it still isn't clear what is going on, re-writing the code in a more meaningful way will help. To make things easier, you can use temporary variables to work, and assign the values to the pointers passed as arguments only at the end of the function. Using more meaningful names also helps a lot.
void read_matrix(int *rows, int *columns, int ***matrix) {
int i, j, r, c;
int **mat;
printf("n = ");
scanf("%d", &r);
printf("m = ");
scanf("%d", &c);
// Allocate space for a matrix (i.e. an array of r integer pointers).
mat = malloc(r * sizeof(int*));
// Allocate space for each row of the matrix (i.e. r arrays of c integers).
for (i = 0; i < r; i++)
mat[i] = malloc(c * sizeof(int));
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("a[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
}
*rows = r;
*columns = c;
*matrix = mat;
}
Since we now moved the assignment of the values to the arguments at the end of the function, we got rid of all the annoying pointer dereference operators (*), and the code looks way cleaner.
You can see that what previously was:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
now became:
mat[i] = malloc(c * sizeof(int));
Which is much easier to understand. This is allocating space for an array (a row of the matrix) holding c integers.
What previously was:
(*a) = (int**)malloc((*n) * sizeof(int*));
now became:
mat = malloc(r * sizeof(int*));
This is allocating an array of r integer pointers (which means a matrix of r rows, if each pointer points to a row).
You don't show how this function is called, but presumably it looks something like this:
int n, m;
int **matrix;
reading(&n, &m, &matrix);
So in this context, matrix is defined as a pointer-to-pointer. It can hold the address of the first element of an array of int *, each of which can hold the address of the first element of an array of int.
When &matrix is then passed to this function, you have a pointer-to-pointer-to-pointer, which is what the argument a of reading is. In this context, a contains a pointer to a single int **, specifically matrix in the calling function. By dereferecing a in reading, you're actually accessing matrix in the calling function.
So now getting to this line:
(*a) = (int**)malloc((*n) * sizeof(int*));
This allocates space for an array of *n int * and assigns that to *a, (i.e. matrix in the calling funtion. So now you have an array of int *. Now for this:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
This loops through the elements of the int * array and assigns to each one a pointer to a memory block big enough for *m int.
So you now effectively have a 2D array of int. Note however that this is not the same as an actual 2D array of int which would be declared as int arr[n][m].
First, you are doing too many different things in a single function, which is making it a bit messy. I suggest that you separate out the logic to get the matrix size from the logic to create the matrix:
void get_size(int *n, int *m) {
printf("n=");
scanf("%d", n);
printf("m=");
scanf("%d", m);
}
int **create_matrix(int n, int m) {
int **matrix = malloc(n * sizeof(int*));
for (int i = 0; i < n; i++)
matrix[i] = malloc(m * sizeof(int));
return matrix;
}
void fill_matrix(int **matrix, int n, int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", [i][j]);
}
}
}
From here it is a lot easier to see what is going on, with fewer *s and &s.
Your matrix is implemented as an array of arrays, so
int **matrix = malloc(n * sizeof(int*));
allocates memory for the outer array, while
matrix[i] = malloc(m * sizeof(int));
allocates memory for each of the inner arrays.
int ***a declares a to be a pointer to a pointer to pointer to an int. The caller is required to have their own int ** and to pass its address to this function. For example, the caller might define int **x; and pass &x to this function for the parameter a. I will use x to refer to the caller’s int **.
(*a) = (int**)malloc((*n) * sizeof(int*)); sets the caller‘s pointer (x) to point to space for *n pointers to int. This is preparation for fabricating a matrix of *n rows—memory will be allocated for each row, and we will have a pointer to that memory, so we need n pointers.
Then these lines:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
allocate memory for *n rows. The second line allocates memory for an array of m int and sets x[i] to point to the first element of that memory. Note that since a is an int ***, *a is an int **, and (*a)[i] is an int *. Thus, *a points to an array of int * elements.
Finally, these lines:
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
set each element of the *n by *m array: For each element x[i][j] (referred to as (*a)[i][j], it passes the address of the element (&(*a)[i][j]) to scanf to be set from the input stream.

Why does realloc fails every time?

I have a problem in the code. malloc works and in the while-loop, realloc() works for the first time and when it is called the second time it always fails.
The code is part of an algorithm to get the prime factors of a number.
int main()
{
int n, in, *ar, len = 0;
scanf("%d", &n);
ar = (int *) malloc(1 * sizeof(int));
while(n % 2 == 0){
ar[len] = 2;
len++;
ar = (int *) realloc(ar, len * sizeof(int));
if(ar == NULL){
printf("Error");
return 1;
}
n /= 2;
}
return 0;
}
I tried with len initialized to 1 but it still fails. It is strange it does not fail on the first call but it fails on the second call. I have read other similar questions but I am a beginner and I didn`t understand.
Thanks in advance!
Here in your program, you are accessing an array out of bounds. which leads to undefined behaviour.
initially, when len = 0, in the while loop:
ar[len] = 2; //ar[0] = 2;
len++; //len = 1
ar = (int *) realloc(ar, len * sizeof(int));
//ar is of size 1
then in next iteration, when len = 1
ar[1] = 2; //you cannot access ar[1] as size of `ar` is only 1.
this continues with each iteration. To avoid this do:
//initialize len to 1
int len = 1;
and use ar[len-1] instead of ar[len] in the while loop.
Have a look at this: How dangerous is it to access an array out of bounds?

Code crashes on c, most likely something to do with malloc?

this is quite basic but I've been trying to solve it for a few hours now with no success. This code is supposed to read 3 ints from user input and then, points according to the ints (n = how many, d = dimension, k is unrelated to this part) and create an array of them. For some reason it crashes on the second loop, where it fails to create the second point, but im not sure why. I think it might has something to do with malloc but I'm totally lost, would appreciate any help.
I inserted the input :
5 3 2
1.2 3.4 0.1
2 times before it crashed.
Code is below:
int main(){
double* pdata;
int n,d,k;
scanf("%d %d %d",&n,&d,&k );
SPPoint* parr [n];
for(int i=0; i<n; i++)
{
double darr [d];
for(int j = 0; j < d-1; j++)
{
scanf(" %lf", &darr[j]);
}
scanf(" %lf", &darr[d-1]);
pdata = darr;
parr[i] = spPointCreate(pdata, d, i);
}
}
This is the code for the spPointCreate function:
struct sp_point_t{
double* data;
int dim;
int index;
};
SPPoint* spPointCreate(double* data, int dim, int index){
SPPoint* point = malloc(sizeof(SPPoint*));
if(point == NULL)
{
return NULL;
}
point->data = (double*) malloc(sizeof(data));
for( int i=0 ; i<dim ; i++)
{
point->data[i] = data[i];
}
point->dim = dim;
point->index = index;
return point;
}
SPPoint* point = malloc(sizeof(SPPoint*));
should be: struct SPPoint* point = malloc(sizeof(*point));
point->data = (double*) malloc(sizeof(data));
should be point->data = malloc(dim * sizeof(*point->data));
since you want to allocate dim doubles for your point.
Code is mis-allocating in 2 places
// Bad
SPPoint* spPointCreate(double* data, int dim, int index){
SPPoint* point = malloc(sizeof(SPPoint*)); // allocate the size of a pointer
...
point->data = (double*) malloc(sizeof(data)); // allocate the size of a pointer
Instead avoid mis-coding the type and allocate to the the size of the de-referenced variable.
Also need to allocate N objects.
SPPoint* spPointCreate(double* data, int dim, int index){
size_t N = 1;
SPPoint* point = malloc(sizeof *point * N);// allocate the size of `*point` * N
...
assert(dim >= 0);
N = dim;
point->data = malloc(sizeof *(point->data) * N);
BTW, casting the result of malloc() not needed.
2nd allocation would benefit with a NULL check. More complicated as dim may be 0 and a malloc() return of NULL in that case is OK.
N = dim;
point->data = malloc(sizeof *(point->data) * N);
if (point->data == NULL && N > 0) {
free(point);
return NULL;
}

Dynamic matrix and dynamic values into matrix

This is my code - i init my own values (1 or 0) into a defined matrix.
instead of setting always a hardcoded matrix i want the user to set values and the dimantions of the matrix
scanf("%d %d", &height, &width);
and after building the matrix to initscan his value
scanf("%d", &vall);
Please help me with this i never done something dynamic this way and dont know how to load dynamix matrix with dynamic values straight from the user please show me your syntax for this so i could learn.
printf("How many Row : ");
scanf("%d", &nrow);
rowptr = malloc(sizeof(int) * nrow);
printf("How many Column : ");
scanf("%d", &ncol);
thank you
#include <stdio.h>
#define WIDTH 50
#define HEIGHT 20
void init(int board[][WIDTH], int rows) {
int x, y;
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
board[y][x] = 0;
/* Scatter some live cells: */
board[10][25] = 1;
board[10][26] = 1;
board[10][27] = 1;
board[11][25] = 1;
board[12][26] = 1;
}
You can use malloc() function for this. malloc() takes the number of bytes as parameter and returns a void pointer on success. You'll need to cast it to the pointer of the appropriate data type to use it. Here's an example:
int **board;
scanf("%d %d", &height, &width);
// first allocate memory for pointer to each row
board = (int**) malloc(height * sizeof(int*));
// then allocate memory for each row
for(i = 0; i < height; i++)
board[i] = (int*) malloc(width * sizeof(int));
And when you're done, free up the allocated memory to avoid memory leak. You have to free them in reverse order:
// first free up each row
for(i = 0; i < height; i++)
free(board[i]);
// then free up the pointers to the rows
free(board);
Edit:
For your code, do this:
printf("How many Row : ");
scanf("%d", &nrow);
rowptr = (int**) malloc(sizeof(int) * nrow);
printf("How many Column : ");
scanf("%d", &ncol);
for(i = 0; i < nrow; i++)
rowptr[i] = (int*) malloc(ncol * sizeof(int));
You have to use the malloc() function to assign memory dinamically. It returns a pointer to a block of memory of the requested size. Here's an example:
int size;
int *foo;
printf("How many elements? ");
scanf("%d", &size);
foo = malloc(size * sizeof(int));
// always check if the call succeeded
if(foo == NULL) {
printf("can't allocate memory!");
return;
}
int i;
for(i = 0; i < size; i++) {
printf("enter value for element #%d: ", i + 1);
scanf("%d", &foo[i]);
}
// ...
free(foo); // to avoid memory leaks
free() tells the os that the block you pass in is no longer in use, so it's available for the future.
Now, since you want a matrix, you need a double pointer and you have to call malloc for every "row" (error checking removed for clarity):
int **matrix = malloc(rows * columns * sizeof(int));
int i;
for(i = 0; i < rows; i++)
matrix[i] = malloc(columns * sizeof(int));
To have a solution with a full dynamic arrays of arrays (a 2D matrix with number of rows and columns unknown at compile time), you should use an int ** type to represent your matrix.
int **board = malloc(height * sizeof *board);
for (i = 0; i < height; i++)
board[i] = malloc(width * sizeof **board);
then prototype your functions with an int ** for the board parameter and access your matrix as usual:
int x = board[i][j]; // store in x the element of row i and column j
If you have modern C, say C99, initializing a matrix dimension with variable content is possible. It is called variable length array, VLA. On what concerns your code, you are almost there. Just change your prototypes to something like the following
void init(size_t cols, size_t rows, int board[rows][cols])
such that the bounds come first and are known when you come to the declaration of the matrix.
You could principally allocate such matrices on the stack
int board[rows][cols];
(without initializer) would do, but if your dimension get large you'd risk stack overflow. To declare a matrix on the heap, you could do something like
int (*board)[cols] = malloc(int[rows][cols]);
don't forget to assign initial values to the individual entries board[i][j] and to free the whole matrix at the end of its use.
Edit: seeing all these answers that try to sell you simulations of 2D arrays via pointers to pointers. Don't do such complicated things, just do what the language provides you directly, VLA.

Resources