I need to write a program that will allocate the memory for multiplication table. The problem is that single call of malloc, calloc and realloc is limited to 80 bytes and I don't know how to allocate memory stage by stage.
If anyone could help me I would be grateful.
Here is what I have tried already. It works if I allocate the memory for 400 bytes in one call.
int main()
{
int row = 10;
int col = 10;
int w=0;
int k=0;
int *tab = (int *)malloc(row*col*sizeof(int));
if(tab == NULL)
{
printf("Failed to allocate memory");
return 8;
}
int i=0;
for (w=0; w<row; w++)
{
for(k=0; k<col; k++)
{
*(tab+w*col+k) = ++i;
}
}
for (w=0; w<row; w++){
for(k=0; k<col; k++){
printf("%3d ", *(tab+w*col+k) );
}
printf("\n");
}
free(tab);
return 0;
}
Nested mallocs() are what you'll need to use. But, be careful, because you'll also need to use several frees()!
// 80 bytes
int** table = malloc(row * sizeof(int*));
for (int i = 0; i < row; i++) {
// 80 bytes
table[i] = malloc(col * sizeof(int));
}
// The 6th element in the first row is set to 5.
table[0][5] = 5;
Related
I am trying to reallocate both elements of a 2D-array and also manipulate the values in the 2D-array within the same function. But I just can't seem to get it to work. On compiling the code doesn't show any errors, but when running it will only ever print the amount of lines I specified as the initial_size at the beginning of the main function.
So it seems that the inner realloc is working fine, as it always prints an entire row once it gets started. But the outer realloc is not working, as it will only print a couple of rows.
Note: The real code takes input of unknown size, from getchar() / scanf(). That is why the realloc functions are inside loops in the function.
Simplified version of the function, with error handling omitted:
void func(int ***A) {
int i, j;
int len = 2;
int len2 = 2;
for (i = 0; i < 10; i++) {
// Check to see if a realloc is needed.
if (i >= len) {
len *= 2;
int **tmp = realloc(*A, len * sizeof(int*));
*A = tmp;
printf("Len1 = %d\n", len);
}
len2 = 2;
for (j = 0; j < 20; j++) {
// Check to see if a realloc is needed.
if (j >= len2) {
len2 *= 2;
int *new_row = realloc((*A)[i], len2 * sizeof(int));
(*A)[i] = new_row;
}
// Assign value.
(*A)[i][j] = i * j;
}
}
}
int main() {
int i, j;
int initial_size = 2;
int **A;
// Malloc with a starting size of 2 (could be any size).
A = malloc(initial_size * sizeof(int*));
for (i = 0; i < initial_size; i++) {
A[i] = malloc(initial_size * sizeof(int));
}
// Call function.
func(&A);
// Print the results, row by row.
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
printf("%d, ", A[i][j]);
}
printf("\n");
}
return 0;
}
I have been stuck for a while now, so any help is greatly appreciated :)
When you realloc in the outer loop, you increase the numbers of pointers from two (those created in main) to four.
The value of the two pointers from main are copied to the new memory area.
The value of the two new pointers are indeterminate and that's your problem. You never initialize them by allocating memory - yet you use them in the other loop.
Further, it seems that you realloc the inner array dimensions individually but you only track one length (i.e. len2). That's also a problem.
And the line len2 = 2 between the loops are wrong as you loose information about previously allocated memory.
There are multiple problems in your code:
you reallocate the pointer array but do not initialize the pointers in the newly allocated portion
you only reallocate the first int array pointed to by the pointer array
you do not initialize the newly allocated area in this int array.
Note that 2D-matrices are more idiomatic in C as arrays of arrays, but it is difficult to manipulate such arrays when the outer dimension is not fixed at compile time.
You should use a reallocation function with specified dimensions for the current and target sizes and deal with reallocating and freeing the blocks appropriately. Also avoid triple pointers: just return the potentially reallocated outer array.
#include <stdio.h>
#include <stdlib.h>
int **func(int **A, int rows, int cols, int new_rows, int new_cols) {
int i, j;
/* free the rows that are discarded */
if (new_rows < rows) {
for (i = new_rows; i < rows; i++) {
free(A[i]);
}
}
/* free the outer array if new rows is zero */
if (new_rows == 0) {
free(A);
return NULL;
}
/* reallocate the outer array if required */
if (new_rows != rows) {
A = realloc(A, sizeof(*A) * new_rows);
}
/* reallocate the existing rows */
if (new_cols != cols) {
for (i = 0; i < rows; i++) {
A[i] = realloc(A[i], sizeof(int) * new_cols);
if (new_cols > cols) {
for (j = cols; j < new_cols; j++)
A[i][j] = 0;
}
}
}
/* allocate the new rows (initialized to 0) */
for (i = rows; i < new_rows; i++) {
A[i] = calloc(sizeof(int), new_cols);
}
return A;
}
int main() {
int **A = NULL;
/* reallocate to 10x20 */
A = func(A, 0, 0, 10, 20);
// Print the results, row by row.
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
printf("%d, ", A[i][j]);
}
printf("\n");
}
/* reallocate to 0x0 (free the matrix) */
func(A, 10, 20, 0, 0);
return 0;
}
Note that the above code does not check for memory allocation failure. To deal with this possibility, it would be much simpler to allocate a new array and copy the current values, then free the previous matrix if no allocation error occurred. It would also be more efficient to allocate all rows as a single block of memory. Below is an example of this approach:
#include <stdio.h>
#include <stdlib.h>
int **func(int **A, int rows, int cols, int new_rows, int new_cols) {
int i, j;
int **B = NULL;
if (new_rows == rows && new_cols == cols)
return A;
if (new_rows != 0 && new_cols != 0) {
/* allocate the new matrix */
B = malloc(sizeof(*B) * new_rows);
if (B == NULL)
return NULL;
B[0] = calloc(sizeof(int) * new_cols, new_rows);
if (B[0] == NULL) {
free(B);
return NULL;
}
/* initialize the row pointers */
for (i = 1; i < new_rows; i++) {
B[i] = B[i - 1] + new_cols;
}
/* copy the current data */
for (i = 0; i < new_rows && i < rows; i++) {
for (j = 0; j < new_cols && j < cols; i++) {
B[i][j] = A[i][j];
}
}
}
/* free the previous matrix */
if (A != NULL) {
free(A[0]);
free(A);
}
return B;
}
int main() {
int **A = NULL;
int i, j;
/* reallocate to 10x20 */
A = func(A, 0, 0, 10, 20);
if (A == NULL) {
printf("Matrix reallocation failed\n");
return 1;
}
// Print the results, row by row.
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
printf("%d, ", A[i][j]);
}
printf("\n");
}
/* reallocate to 0x0 (free the matrix) */
func(A, 10, 20, 0, 0);
return 0;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I need to create a 2D Array with 10 columns and an unspecified row amount.
My idea is to malloc the array but unfortunately I don't know how to do that with a 2D Array.
Can someone provide me with a simple code? So far, I have this:
int arr[][10];
int rows = malloc(sizeof(int));
for (int i = 0; i < 10; i++)
{
for(int j = 0; j < ???; j++)
{
arr[?][i] = 5;
}
}
I'm sorry but I'm new to C and I'm struggling with malloc and free.
How and where do I free the memory after?
What should I put instead of ? and ????
row maybe?
Thanks a lot.
If you want to allocate memory you will eventually need to know the amount you need, there is no two ways about it, you can however declare a pointer to array of a fixed number of columns, and later when you know the number of rows, allocate the space you need.
Sample code with comments:
int main()
{
//pointer to an array with 10 columns
//at this point the number of rows is not required
int(*arr)[10];
//to allocate memory you need to know how much of it you need
//there is no two ways about it, so when you eventually know
//the number of rows you can allocate memory for it
arr = malloc(sizeof *arr * 5); // 5 is the number of rows
if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
{
arr[i][j] = 5;
}
}
free(arr); //free the memory when your are done using arr
}
Another option is to reallocate memory as you go, for each new row:
Live demo
for (int i = 0; i < 5; i++)
{
//allocate memory for each new row
arr = realloc(arr ,sizeof *arr * (i + 1));
if(arr == NULL){
perror("malloc");
return EXIT_FAILURE;
}
for (int j = 0; j < 10; j++)
{
arr[i][j] = 5;
}
}
Test printing the array:
for (int i = 0; i < 5; i++) //test print the array
{
for (int j = 0; j < 10; j++)
{
printf("%d", arr[i][j]);
}
putchar('\n');
}
Will output in both cases:
5555555555
5555555555
5555555555
5555555555
5555555555
Maybe a typedef will help you?
#include <stdio.h>
#include <stdlib.h>
void seqr(void *d, int n) {
int *a = d;
for (int k = 0; k < n; k++) a[k] = k;
}
typedef int row10[10]; // helper typedef
int main(void) {
int n = 42;
row10 *rows = malloc(n * sizeof *rows);
if (rows) {
seqr(rows, n * 10);
printf("%d, %d\n", rows[0][0], rows[n - 1][9]);
free(rows);
}
return 0;
}
The following is my code and I cannot figure out where I am going wrong to free my 2d array.
I know that the error happens at this line: free(arr[i]); and I also know that I have to do this loop to free each integer before freeing the entire array later. Can anyone spot the bug here? I get no compilation errors, but once running my executable, there is a huge backtrace output for the free function.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int h = 4;
int w = 2;
int i, j;
int **arr = (int**)malloc(sizeof(int*) * h);
arr[0] = (int*)malloc(sizeof(int) * w * h);
for (i=1; i<h; i++)
{
arr[i] = arr[0] + (w*i);
}
int count = 0;
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
arr[i][j] = count++;
}
}
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
}
printf("\n");
}
for (i=0; i<h; i++)
{
free(arr[i]);
}
free(arr);
/*printf("\nAfter freeing the array it becomes:\n");
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
}
printf("\n");
}*/
}
you are allocating memory for arr[0] = (int*)malloc(sizeof(int) * w * h); only but while freeing the allocated space you are freeing up to h count, for (i=0; i<h; i++){free(arr[i]);}. You should have allocated this way as well using the same loop.
The memory you are allocating in the call
arr[0] = (int*)malloc(sizeof(int) * w * h);
is enough for the entire 2D array. If you want to use this approach, i.e., allocate memory for the 2D array in a single call to malloc, you can do so by casting the returned pointer to pointer-to-array of w elements. Then you can also free the memory in a single call to free. No need to use the for-loop. See the code below.
int main()
{
int h = 4;
int w = 2;
int i, j;
int (*arr)[w] = (int(*)[w])malloc(sizeof(int)*h*w); // pointer to array of w ints
int count = 0;
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
arr[i][j] = count++;
}
}
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
}
printf("\n");
}
free(arr); //<-- free the 2D array in a single free
return 0;
}
When you use your malloc's you allocate only the first position of the array
arr[0] = (int*)malloc(sizeof(int) * w * h);
This means than when you have to free your memory you need to call free(arr[0]) and then free(arr)
This will not give you an error.
Anyway, I don't think this is what you want to do. You probably want a solution more on the lines of:
int **arr = (int**)malloc(sizeof(int*) * h);
for (int i = 1; i < h ; ++i){
arr[i] = (int*)malloc(sizeof(int) * w); // with the correct size you want
}
This will allocate h pointers in the array for use, then you can free the memory like you did in your example
EDIT: Please note that like #AndrewHenle correctly pointed out in his comment this solution doesn't allocate a true 2D array but just an array of pointers to arrays. For a way to properly allocate a 2D array please see this related question
//for (i=0; i<h; i++) { free(arr[i]); }//error
free(arr[0]); //true
free(arr);
i have this small piece of code which i cant get to work.
I am kinda new and i just cant find a mistake i did. Thanks
int main (void)
{
int **array;
int i,j, m;
scanf("%d", &m);
array = malloc(sizeof(int) * (m*m));
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &array[i][j]);
}
}
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
{
printf("%d", array[i][j]);
}
}
return 0;
}
What you are allocating is an one dimensional array of size m*m but you are using it as if you have allocated a jagged array where each row contains m elements.
You can allocate a bit different way than what you did
array = malloc(sizeof *array * m);
if( array == NULL)
{
// error in malloc
}
for(size_t i =0; i<m; i++)
{
array[i]= malloc(sizeof *array[i] * m);
if( array[i] == NULL)
{
// error
}
}
...
for(size_t i = 0; i<m ; i++)
free(array[i]);
free(array);
Alternatively you can put all the elements in a linear manner using i and j.
int *array;
...
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
{
if( scanf("%d", &array[i*m+j]) != 1){
// error in getting input.
}
}
}
...
free(array);
Same goes with printf also.
Also don't forget to free the memory you have allocated dynamically after you are done working with it.
gcc 4.6.2 c89
Allocating memory for a 2D array and filling with characters.
However, I don't seem to be filling as when I print nothing is displayed.
Am I doing something wrong here?
char **attributes = NULL;
/* TODO: Check for memory being allocated */
attributes = malloc(3 * sizeof(char*));
int i = 0;
int k = 0;
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
printf("attributes[i][k] [ %c ]\n", attributes[i][k]);
}
}
Many thanks for any advice,
Two major issues:
First Issue:
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
You are reallocating sdp_attributes[i] at each iteration of the inner loop - thereby overwriting it each time. You probably wanted this instead:
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
Second Issue:
sdp_attributes[i][k] = k;
You are basically writing the lower ascii characters. Most of them are not printable.
Something like this might do what you want:
sdp_attributes[i][k] = k + '0';
You probably want:
for (i = 0; i < 3; i++)
{
attributes[i] = malloc(5 * sizeof(char));
for (k = 0; k < 5; k++)
{
attributes[i][k] = k;
}
}
This ignores error checking on the allocation.
It also fixes the name of the array to match the declaration, but your code either wasn't compiling (don't post non-compiling code unless your question is about why it doesn't compile!) or you have another variable called sdp_attributes declared somewhere which you weren't showing us.
Your code was leaking a lot of memory. Each time around the k-loop, you allocated a new array of 5 characters and stored the pointer in attributes[i] (or sdp_attributes[i]), storing the new pointer over what was there before, so you overwrote the value of the first 4 pointers. You could not possibly free the first four items - they were lost irretrievably. Also, on the last iteration, you initialized the 5th element of the final array, but the previous 4 were not initialized and therefore contained indeterminate garbage.
Also, in your printing loop, the values in the array are control characters ^#, ^A, ^B, ^C and ^D; these do not necessarily print well with %c (especially not ^#, which is also known as NUL or '\0'). The printf() statement might be better written as:
printf("attributes[%d][%d] [ %d ]\n", i, k, attributes[i][k]);
This prints the array indexes (rather than simply the characters [i][k] for each entry), and prints the control characters as integers (since the char values are promoted to int when passed to printf()) rather than as control characters.
(It's also more conventional to use i and j for a pair of nested loops, and i, j, and k for triply nested loops, etc. However, that's a very minor issue.)
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
Your erasing the allocated memory every time you loop in the inner most loop.
Here is a correct version.
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
sdp_attributes[i][k] = k;
}
}
And you should fix your declaration:
attributes = malloc(3 * sizeof(char*));
to
sdp_attributes = malloc(3 * sizeof(char*));
Don't forget to free up all the memory allocated
for(i = 0; i < 3; i++)
{
free(sdp_attributes[i]);
}
free(sdp_attributes);
The correct way to allocate and assign elements to 2d array is as follows (but this is a int array, you can try and change it for char array):
One thing to note: As mentioned by #Mysticial, you should add/subtract '0' to your int value to get the char value when using ASCII character set (remember our itoa() functions!).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int row, column;
int **matrix;
int i, j, val;
printf("Enter rows: ");
scanf("%d", &row);
printf("Enter columns: ");
scanf("%d", &column);
matrix = (int **) malloc (sizeof(int *) * row);
for (i=0 ; i<row ; i++)
matrix[i] = (int *) malloc (sizeof(int) * column);
val=1;
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
matrix[i][j] = val++;
}
}
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
for (i=0 ; i<row ; i++)
free(matrix[i]);
free(matrix);
return 0;
}
Few points to note:
error handling should be added for malloc()
malloc()'ed memory must be free()'ed