Multi-dimensional (2D) array dynamically using malloc()? - c

Please if someone tell me what is wrong with this code by using malloc function, I dont know what to do.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>
int main()
{
int row;
int column;
int j=0;
int **ptr;
printf("Number of rows: \n");
scanf ("%d",&row);
printf("Number of columns: \n");
scanf ("%d",&column);
There is a mistake, ???? please if someone know what to do to write
int* ptr = malloc( row * sizeof(*ptr) ); /*Allocate integer pointers for the rows */
if(ptr != NULL)
{
for(int m = 0; m < row; m++) /* Loop through each row pointer to allocate memory for columns*/
{
/* Set p[i] pointer to a block of memory for 'column' number of integers */
ptr[m] = malloc(column * sizeof **ptr); /*Here, sizeof(**p) is same as sizeof(int) */
if(ptr[m] == NULL)
{
printf("Memory allocation failed. Exiting....");
exit(1);
}
}
}
else
{
printf("Memory allocation failed. Exiting....");
exit(1);
}
for(int i=0; i<row; i++)
{
for(int j=0; j<column; j++)
{
printf("Enter values [%d] [%d]: \n",i+1,j+1 );
scanf ("%d",&ptr[i][j]);
}
}
free (ptr);
system("PAUSE");
return 0;
}
Pleas for answer because i need this code in school till 3. Jan. 2014

Change this line…
int* ptr = malloc( row * sizeof(*ptr) );
… to this…
ptr = malloc( row * sizeof(*ptr) );
You've already declared ptr here:
int **ptr;

If you feel the need to use malloc (and free) for dynamic allocation, then there are some good answers already here. But please consider that you do not need to use malloc at all in your example.
You can simply declare an automatic array of variable size as shown below. Your code will be very clear and the potential for bugs will be reduced. This feature is available in the C language since ISO C99 (earlier, in some compliers).
There can be an argument to not use variable sized array declaration if the array will be extremely large. Your example is taking user input for each array element, so that tells me you're not allocating hundreds of megabytes or anything that would blow up the stack! So this will work for you just fine. Good luck.
#include <stdio.h>
int main()
{
int rows;
int columns;
printf("Number rows: ");
scanf ("%d", &rows);
printf("Stevilo columns: ");
scanf ("%d", &columns);
int values[rows][columns]; /* <-- no need to malloc(), no need to free() */
for(int i=0; i<rows; i++) {
for(int j=0; j<columns; j++) {
printf("Enter value[%d][%d]: ",i+1,j+1 );
scanf("%d", &values[i][j]);
}
}
}

Instead of using sizeof (ptr) and sizeof **ptr, try to use sizeof(int*) in the first malloc, and sizeof(int) in the second malloc.

thank you all for so fast answers, it was very helpful, now it works without any error!
I did so:
int** ptr = (int**) malloc(row * sizeof(int)); /*Allocate integer pointers for the rows */
if(ptr != NULL)
{
for(int m = 0; m < row; m++) /* Loop through each row pointer to allocate memory for columns*/
{
/* Set p[i] pointer to a block of memory for 'column' number of integers */
ptr[m] = (int*)malloc(column * sizeof(int)); /*Here, sizeof(**p) is same as sizeof(int) */
if(ptr[m] == NULL)
{
printf("Memory allocation failed. Exiting....");
exit(1);
}
}
}
else
{
printf("Memory allocation failed. Exiting....");
exit(1);
}

First off your code is very messy. Your malloc call should also look like this for example:
int** ptr = (int**)malloc(row * sizeof(ptr*));
The size of a pointer will always (almost all the time unless you are on a computer made in 1982) be 4 because its a memory address aka an int wich is 4 bytes. In your for loop it should read something like:
ptr[m] = (int*)malloc(column * sizeof(ptr));

Related

Error: subscripted value is not an array, pointer, or vector and idk what the issue is? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
The purpose of this exercise is to use the two-subscript method of dynamic memory allocation.
Input for this program is a two-dimensional array of floating point data located in a file named
testdata2. The input array will contain 3 rows of data with each row containing 5 columns of data.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
int temp;
int number;
int r = 3;
int c = 5;
fp = fopen("testdata2.txt", "r");
number = (int)malloc(r * c * sizeof(int));
while (fscanf(fp, "%d", &temp) != EOF){
for(int i = 0; i < 3;i++){
for(int j = 0; j < 5; j++){
temp = number[i][j];
}
}
}
return(0);
}
Among the plethora of things incorrect in your code (any one of which can result in undefined behavior):
The core data type is wrong. The question specifically calls for floating-point values, yet you're using integer types.
The receiver of any memory allocation in C should be a pointer; you're using a simple int.
You're hiding whatever warnings/errors you're receiving by hard-casting. Casting malloc in C isn't necessary, nor advised.
Even if everything else were fixed, your assignment statement for temp = ... is backward. You want to save the value just-read into your matrix, not throw it away and overwrite it with whatever undefined value resides in your memory-just-allocated.
All of that said, knowing the width of your array of arrays is five, the problem reduces to this. Note temp isn't needed at all
#include <stdio.h>
#include <stdlib.h>
int main()
{
static const size_t r = 3;
static const size_t c = 5;
FILE *fp = NULL;
double (*number)[c] = NULL; // pointer to array of dimension c.
fp = fopen("testdata2.txt", "r");
if (fp == NULL)
{
perror("Failed to open file: ");
return EXIT_FAILURE;
}
number = malloc(r * sizeof *number); // allocate r-rows of dimension c
if (number == NULL)
{
perror("Failed to allocate array of arrays: ");
return EXIT_FAILURE;
}
for (size_t i=0; i<r; ++i)
{
for (size_t j=0; j<c; ++j)
{
if (fscanf(fp, "%lf", number[i]+j) != 1)
{
fprintf(stderr, "Failed to parse int at %zu,%zu", i, j);
return EXIT_FAILURE;
}
}
}
for (size_t i=0; i<r; ++i)
{
for (size_t j=0; j<c; ++j)
printf("%lf ", number[i][j]);
fputc('\n', stdout);
}
free(number);
return(0);
}
You are declaring an integer:
int number;
and you are allocating memory with malloc assuming it is a multi-dimensional array, then trying to access its elements in the same way.
Change the declaration to:
int **number;
it is not
(int)malloc(rcsizeof(int))
It is
(int*) malloc(rcsizeof(int))
One more mistake is that you can't access the elements as
temp=number[i][j];
Replace it with
temp=number[i*r+j]
Hope this helps
number = (int)malloc(r * c * sizeof(int));
In C, never cast the result of a malloc. If you had left out the cast to int, you'd have a diagnostic here telling you that number is not a pointer type.
You can do this:
int* number = malloc(r * c * sizeof(int));
But that gives you one big single dimensional array. You would need to dereference it like this:
temp = number[i * c + j];
If you want two dimensional indices as if you had declared it like this:
int number[r][c];
you need to allocate it in two stages:
int** number = malloc(r * sizeof(int*));
number[0] = malloc(r * c * sizeof(int));
for (int i = 1 ; i < r ; i++)
{
number[i] = &number[0][i * c];
}
That sets up a big array of ints and an intermediate array of pointers to ints for each row. Now you can do
temp = number[i][j];
Edit
Or you can do what Dmitri says which is this:
int (*number)[c] = malloc(r * c * sizeof(number[0][0]));
That effectively mallocs an array of r blocks of c ints in one go.

Issue Creating and Freeing C Dynamic Arrays

I am writing a C program that involves passing 2D arrays between functions changing their size and entries. I decided to use dynamic arrays with pointers for this.
Whenever I free the pointers to an array, I find that I wipe the values held in other arrays. I can successfully change which array a pointer points to. I believe this is an issue with the way I'm freeing my pointers or declaring them. Below is code I'm using to create and free pointers to my arrays.
int** create_array(int m, int n)
{
int i;
int* values = calloc(m * n, sizeof(int));
int** rows = malloc(n * sizeof(int*));
for(i = 0; i < n; i++) {
rows[i] = values + (i * m);
}
return rows;
}
void destroy_array(int** arr)
{
free(arr[0]);
free(arr);
}
OLD CODE to Create and Free Pointers
int** create_array(int m, int n)
{
int i;
int* values = calloc(m * n, sizeof(int));
int** rows = malloc(n * sizeof(int*));
for(i = 0; i < n; i++) {
rows[i] = values + (i * m * sizeof(int));
}
return rows;
}
void destroy_array(int** arr, int m, int n)
{
int i;
for(i = 0; i < n; i++) {
free(arr[i]);
}
free(arr);
}
My program gets a segfault after I destroy the pointers to an array and try to read values from another array. Below is the code where I destroy my pointers to these arrays. positions_last and positions are both arrays that I can read from properly before this point.
positions_last = positions;
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
fflush(stdout); // this prints fine
destroy_array(positions);
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
fflush(stdout); // this does not print, I get a segfault at this point
I just did an elementary test which suggests that the issue lies in my current code for creating or destroying arrays (so far as I know).
int** positions2 = create_array(10, 3);
int** positions3 = create_array(10, 3);
printf("%d %d %d", positions3[0][1], positions3[1][1], positions3[2][1]);
fflush(stdout); // This line prints fine
positions3 = positions2;
destroy_array(positions2);
printf("%d %d %d", positions3[0][1], positions3[1][1], positions3[2][1]);
fflush(stdout); // This line triggers a segfault
Anyone have an idea what the issue may be?
You called calloc once and malloc once, but then you're calling free n+1 times (and of course you're freeing the same value, arr[1] n times). There should be exactly one free for each malloc or calloc.
void destroy_array(int** arr)
{
free(arr[0]);
free(arr);
}
This line
rows[i] = values + (i * m * sizeof(int));
should be
rows[i] = values + (i * m);
The reason behind this is that values is a typed pointer, namely pointing to int. Adding 1 to it increases it by 1 * sizeof (int). Your code assumes it would be increased by 1 only.
This are basic pointer arithmetics: http://cslibrary.stanford.edu/104/ ;-)
So you are running into undefined behaviuor even before the 1st call to free().
Also malloc/calloc and free follow the pattern:
One Allocation --> One Freeing
So freeing might look like this:
free(*arr); /* Free what had been allocated to "values". */
free(arr); /* Free what had been allocated to "rows". */
The code you show does differently, as pointed out by zindorsky's answer.
Regarding your edit:
This
positions_last = positions;
does not copy the array, its elements, but just the reference to the array 1st member. SO if you deallocate positions also positions_last points to freed, that is then invalif memory. Accessing it provokes UB, as this lines does:
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
Lesson learned: In C one cannot copy an array by a simple assignment

correct way to free m*n matrix bidimensional allocation

I allocate a non-square matrix in this way, but I'm not sure if I'm using the deallocation correctly
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m*sizeof(*arr));
for(i=0; i<m; i++)
{
arr[i]=malloc(n*sizeof(**arr));
}
return arr;
}
I have tried two way to free the memory
-Attempt A loop rows
void free_mem_mat(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
- Attempt B loop columns
void free_mem_mat(int n, float **array) {
int i;
for (i = 0; i < n; i++) {
free(array[i]);
}
free(array);
}
what should I use to free? the way A on the rows or the way B? (I know as written the method is the same I have rewritten this to be most clear possible)
You need one free() for each malloc()*. There were m+1 calls to malloc(); you'd better make m+1 calls to free() too.
Given that as the starting point, option A is the correct solution. However, it is also fair to note that the two functions (option A and option B) are strictly equivalent as long as you pass the m dimension given to the allocation function as the size argument of the deallocation function. The comment in option B is misleading; you're not looping over columns.
Given:
enum { MAT_ROWS = 20, MAT_COLS = 30 };
float **matrix = matrix_alloc(MAT_ROWS, MAT_COLS);
The correct call to free_mem_mat() is:
free_mem_mat(MAT_ROWS, matrix);
* This is an over-simplified statement if you use realloc() or calloc(). You need a free() for each malloc() that was not realloc()'d, and a free() for each realloc() that did not do a free() — by setting the size to 0. Treat calloc() as equivalent to malloc() as far as free() is concerned.
The trouble is that it has many allocations
I prefer this mode
#include <stdio.h>
#include <stdlib.h>
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m * sizeof(float *));
*(arr) = malloc(m * n * sizeof(float));
for (i = 0; i < m; i++) {
*(arr + i) = (*(arr) + i * n);
}
return arr;
}
void free_mem_mat(float **array) {
free(*(array));
free(array);
}
int main () {
float **matrix = matrix_alloc(10, 20);
free_mem_mat(matrix);
return 0;
}
more information in:
http://c-faq.com/aryptr/dynmuldimary.html
arr was allocated as an array of m elements, each a pointer to some allocated memory. Therefore, you must free the m pointers in arr. In freeing each, you don't need to mention the size of the thing pointed to.

How to malloc a 2d jagged array using a pointer passed by reference to a function in C

I have a 2D jagged array declared in my main() block. This is to be passed to a function to have memory allocated to it. The following is the most reduced case which compiles but crashes when it runs. Where am I going wrong?
#include <stdio.h>
#include <stdlib.h>
void alloc2d(double ***p);
int main () {
double **data;
alloc2d(&data);
printf("Before assign to data\n");
data[0][0] = 0.1;
printf("After assign to data\n");
free(data);
}
void alloc2d(double ***p) {
int i, n, m;
// Get some dynamically assigned sizes
printf("Enter size: ");
scanf("%d %d", &n, &m);
// Now allocate
*p = malloc(n * sizeof(double*));
for (i = 0; i < n; i++) {
*p[i] = malloc(m * sizeof(double));
}
printf("End of alloc2d\n");
}
This reads the values but crashes when I enter low numbers (i.e. '1 1') but crashes when I enter high numbers (i.e. '10 10').
You made a very simple syntax error
*p[i] = (double*)malloc(m * sizeof(double));
should really be
(*p)[i] = (double*)malloc(m * sizeof(double));
This is because in C, [] operator has higher precedence than *.
So when you type *p[i],
it is translated into **(p + i).
This means: you are asking the compiler to calculate the address by offsetting the address of p by i * sizeof(double**), which is clearly not what you actually want.
So, in order to force the compiler to dereference p first, simply surroud *p with brackets.
Operator precedence is the answer. *p[i] is equivalent to *(p[i]). This makes you access memory that lies right after the data pointer, which will either corrupt some other variables on the stack, or crash completely.
You were looking for (*p)[i], which will be the i-th entry in the newly allocated array.
What your alloc2d() allocates is not really a 2D array, but:
1 1D n-long array of pointers to double
n 1D m-long arrays of doubles
Multi-dimensional arrays in C are only possible, if all but the last of the dimensions are known at compile-time:
double a[5][11];
Maybe, this program can help you understand... Note, how COLUMNS is a compile-time constant, even if rows is a run-time variable:
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <err.h>
typedef double myrow_t[11]; /* 11 columns */
#define COLUMNS (sizeof(myrow_t)/sizeof(double))
static unsigned
alloc2d(myrow_t **pd)
{
unsigned int rows;
printf("Enter the number of rows: ");
while (scanf("%u", &rows) != 1)
printf("\ninvalid input, please, try again: ");
*pd = malloc(rows * sizeof(**pd));
if (*pd == NULL)
err(EX_TEMPFAIL, "Out of memory");
return rows;
}
int
main()
{
myrow_t *d;
unsigned int row, column, rows;
rows = alloc2d(&d);
for (row = 0; row < rows; row++)
for (column = 0; column < COLUMNS; column++)
d[row][column] = row * column;
for (row = 0; row < rows; row++) {
printf("Row %3d:\t", row);
for (column = 0; column < COLUMNS; column++)
printf("%.0f\t", d[row][column]);
puts("");
}
free(d);
return 0;
}

How to cycle through array without indexes in C?

I need to allocate an N sized array and assign it values, how can I do it without int indexes?
Here is the code I have so far but it doesn't do what I need:
#include <stdlib.h>
#include <stdio.h>
int main() {
int *array;
int n;
printf("Size of array: ");
scanf("%d", &n);
array = (int*) malloc(n*sizeof(int));
if (array == NULL) printf("Memory Fail");
for(; *array; array++)
{
printf("Store:\n");
scanf("%d", &n);
*array = n;
}
for(; *array; array++)
{
printf("Print: %d\n",*array);
}
free(array);
return 0;
}
thanks
for(; *array; array++); you should remove ; at the end
Number of iterations for this loop is undefined and you are going to lose a pointer
You should do something like this:
int *cur;
for(cur = array; cur < array+n; ++cur)
{
*cur = ...;
}
When you allocate the memory, you have no way to determine, in the memory, where it ends (unless you decide a convention and set a value somewhere, but anyway you would use n) .
In your case you have to use n to limit the array coverage (otherwise it is only limited by your computer capacity, and until it reaches an area where it does not have access: program crash). For instance (be careful not to overwrite n !)
int v;
int x = n;
int *ptr = array;
while (x--)
{
printf("Store:\n");
scanf("%d", &v);
*ptr++ = v;
}
x = n;
ptr = array;
while (x--)
{
printf("Print: %d\n",*ptr++);
}
You are using *array as your condition, which means the for loop should continue unless *array evaluates to false, which is only if *array == 0. You are actually invoking undefined behavior because you allocate array with malloc and are trying to dereference the pointer when the underlying data could be anything, since the data block has been uninitialized.
You still need some type of counter to loop with, in this case you allocated n items.
/* I'm using a C99 construct by declaring variables in the for initializer */
for (int i = 0; i < n; ++i)
{
/* In your original code you re-assign your counter 'n', don't do that otherwise you lost the size of your array! */
int temp;
printf("Store: \n");
scanf("%d", &temp)
array[i] = temp;
}
/* This is your second loop which prints the items */
for (int i = 0; i < n; ++i)
{
printf("%d\n", array[i]);
}
Also, do not manipulate the array pointer without keeping a copy of it. You can only do free on the pointer returned by malloc.
Using indexes is the same as manipulating the pointer, your professor is being ridiculous otherwise.
If you have an array int *a; then:
a[0] is equal to *a
a[1] is equal to *(a+1)
a[2] is equal to *(a+2)
So you can go through the array by doing arithmetic on the pointer.

Resources