I'm trying to write a program that calculates the number of elements of given matrix,for example M[2][3] = [1,2,3][3,4,5]
should give the number of elements from 0 trough 9 in a nxm array.
The algorithm is correct up until line 34(M[i][j] = i + 2;) in which I'm having a segmentation fault.
What am I doing wrong?
#include<stdio.h>
#include<stdlib.h>
#define ROW 10
#define COL 10
#define MAX 10
void Print_Matrix(int **M,int row,int col);
int MallocX(int **M,int row,int col);
int main(void)
{
int **M = 0x0;
int count[MAX] = {0};
int i,j;
if(MallocX(M,ROW,COL)){
fprintf(stdout,"Could not allocate memory\n");
exit(1);
}
for(i = 0;i<ROW;i++){
for(j = 0;j<COL;j++){
M[i][j] = i + 2;
}
}
Print_Matrix(M,ROW,COL);
for(i = 0;i<ROW;i++){
for(j = 0;j<COL;j++){
++count[M[i][j]];
}
}
for(j = 0;j<MAX;j++){
if(count[j]){
printf("%d %d\n",j,count[j]);
}
}
for(i = 0;i<ROW;i++){
free(M[i]);
}
free(M);
}
int MallocX(int **M,int row,int col)
{
int i;
M = (int **) malloc(row * sizeof(int *));
if(M == NULL){
fprintf(stderr,"Error allocating memory\n");
free(M);
return 1;
}
for(i = 0;i<row;i++){
M[i] = (int *) malloc(col * sizeof(int));
if(M[i] == NULL){
fprintf(stderr,"Error allocating memory\n");
free(M[i]);
return 1;
}
}
return 0;
}
void Print_Matrix(int **M,int row,int col)
{
int i,j;
for(i = 0;i<row;i++){
for(j = 0;j<col;j++){
printf("%d ",M[i][j]);
}
printf("\n");
}
}
This is because you are passing M by value, not reference. Your MallocX allocates memory for your matrix, but those allocations are orphaned when you return to the main program, where M is still 0x0 (or NULL), which is why allocation functions typically return a pointer. Perhaps you want something like this:
int **MallocX(int row,int col)
{
int **Matrix, i;
Matrix = malloc(row * sizeof(int*));
if(Matrix == NULL) {
fprintf(stderr,"Error allocating memory\n");
return NULL;
}
for (i = 0; i < row; i++) {
Matrix[i] = (int*) malloc(col * sizeof(int));
if(Matrix[i] == NULL){
fprintf(stderr,"Error allocating memory (%d)\n",i);
for (int j = 0; j < i; ++j)
free(Matrix[j]);
free(Matrix);
return NULL;
}
}
return Matrix;
}
Then in main, call it with:
if (!(M = MallocX(ROW,COL)) {
fprintf(stdout,"Could not allocate memory\n");
exit(1);
}
Note that in your original code, you were calling free(M) when M was NULL, which will itself cause a segfault. So I've tidied up your garbage collection a bit too.
Related
I believe this code forces memory allocation for a 3-d array to be contiguous.
void ***calloc_3d_array(size_t n3, size_t n2, size_t n1, size_t size){
void ***array;
size_t i, j;
if ((array = (void***)calloc(n3, sizeof(void**))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
(int)n3);
return NULL;
}
if ((array[0] = (void**)calloc(n3*n2, sizeof(void*))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
(int)(n3*n2));
free((void*)array);
return NULL;
}
for (i=1; i<n3; i++) {
array[i] = (void**)((unsigned char*)array[0]+i*n2*sizeof(void*));
}
if ((array[0][0] = (void*)calloc(n3*n2*n1, size)) == NULL) {
printf("[calloc_3d] failed to alloc. memory (%d X %d X %d of size %d)\n",
(int)n3, (int)n2, (int)n1, (int)size);
free((void*)array[0]);
free((void*)array);
return NULL;
}
for (j=1; j<n2; j++) {
array[0][j] = (void**)((unsigned char*)array[0][j-1]+n1*size);
}
for (i = 1; i < n3; i++) {
array[i][0] = (void**)((unsigned char*)array[i-1][0]+n2*n1*size);
for (j = 1; j < n2; j++) {
array[i][j] = (void**)((unsigned char*)array[i][j-1]+n1*size);
}
}
return array;
}
I am trying to alter this into a function that allocates a 4-d array contiguously. I do not fully understand the 3-d case flawless, so abstracting to a 4th dimension is a little shaky. I mostly unsure exactly why in any loop we have either array[i] = (void**) or array[i][j] = (void**) in the 3d code, so in the 4d code I have all the array[i][j][k] = (void***). Here is what I currently have
void ****calloc_4d_array(size_t n4, size_t n3, size_t n2, size_t n1, size_t size){
void ****array;
size_t i, j, k;
/* Alloc array of 3d pointers */
if ((array = (void****)calloc(n4, sizeof(void***))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
(int)n4);
return NULL;
}
/* In first slot allocate a entire 2d pointer array */
if ((array[0] = (void***)calloc(n4*n3, sizeof(void**))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
(int)(n4*n3));
free((void*)array);
return NULL;
}
/* Loop over slots and adjust address to accommodate 2d pointers */
for (i = 1; i < n4; i++) {
array[i] = (void***)((unsigned char*)array[0]+i*n3*sizeof(void**));
}
/* In the first 2d pointer, allocate the entire space for 1d pointers*/
if ((array[0][0] = (void**)calloc(n4*n3*n2, sizeof(void*))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 3rd-pointers\n",
(int)(n4*n3*n2));
free((void*)array[0]);
free((void*)array);
return NULL;
}
/* Loop over other 2d slots and adjust address to accommodate type */
for (j=1; j<n3; j++) {
array[0][j] = (void**)((unsigned char*)array[0][j-1]+n2*size);
}
for (i=1; i<n4; i++) {
array[i][0] = (void**)((unsigned char*)array[i-1][0]+n3*n2*size);
for (j=1; j<n3; j++) {
array[i][j] = (void**)((unsigned char*)array[i][j-1]+n2*size);
}
}
/* Finally allocate for entire array */
if ((array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size)) == NULL) {
printf("[calloc_3d] failed to alloc. memory (%d X %d X %d X %d of size %d)\n",
(int)n4, (int)n3, (int)n2, (int) n1, (int)size);
free((void*)array[0][0]);
free((void*)array[0]);
free((void*)array);
return NULL;
}
for (k=1; k<n2; k++) {
array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);
}
for (j=1; j<n3; j++) {
array[0][j][0] = (void***)((unsigned char*)array[0][j-1][0]+n2*n1*size);
for (k=1; k<n2; k++) {
array[0][j][k] = (void***)((unsigned char*)array[0][j][k-1]+n1*size);
}
}
for(i=1; i<n4; i++) {
array[i][0][0] = (void***)((unsigned char*)array[i-1][0][0]+n3*n2*n1*size);
for (j=1; j<n3; j++) {
array[i][j][0] = (void***)((unsigned char*)array[i][j-1][0]+n2*n1*size);
for (k=1; k<n2; k++) {
array[i][j][k] = (void***)((unsigned char*)array[i][j][k-1]+n1*size);
}
}
}
return array;
}
Edit: The compiler gave me a warning relating to my (void***) question, and it seems to make sense that array[][] is a (void**), but I still don't know why it is happy with array[i] = (void***) instead of array[i] = (void*). Otherwise said, why is it (void*) with calloc array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size), but (void***) when using the bit shifting/setting the address(?) array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);? I would think whatever kind of object array[][][] is either (void*) or (void***).
This should allocate 2 and above dimensions array continuously use recursion. Suggest use FORTRAN for such kind of high dimensional computation, this is not memory efficient. The example seems valgrind clean.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void *alloc_nd(int *dim, int nd, size_t size)
{
assert(nd>=2);
void **p = malloc(sizeof(void*)*dim[0]);
if(nd==2) {
p[0] = malloc(size*dim[0]*dim[1]);
for(int i=1; i<dim[0]; i++)
p[i] = p[i-1]+size*dim[1];
} else {
int xd[nd-1];
for(int i=1; i<nd; i++)
xd[i-1] = dim[i];
xd[0] *= dim[0]; //callapse the 1st two dimension
p[0] = alloc_nd(xd, nd-1, size);
for(int i=1; i<dim[0]; i++)
p[i] = p[i-1]+sizeof(void*)*dim[1];
}
return p;
}
void free_nd(void *p, int nd)
{
if(nd==2) {
free(((void**)p)[0]);
free(p);
} else {
free_nd(((void**)p)[0], nd-1);
free(p);
}
}
int main()
{
int dim[] = {3,4,5,6};
int ****array;
array = (int****)alloc_nd(dim, 4, sizeof(int));
for(int i0=0; i0<dim[0]; i0++)
for(int i1=0; i1<dim[1]; i1++)
for(int i2=0; i2<dim[2]; i2++)
for(int i3=0; i3<dim[3]; i3++)
array[i0][i1][i2][i3] = i0+i1+i2+i3;
int *p = &array[0][0][0][0]; //do you mean continuous in this way?
for(int i=0; i<dim[0]*dim[1]*dim[2]*dim[3]; i++)
printf("p[%5d]=%d\n", i, p[i]);
free_nd(array, 4);
return 0;
}
All the solutions I have seen online has calloc() function used twice, is it possible to do with only using it once?
The below code is not printing the correct array elements
int **ptr;
//To allocate the memory
ptr=(int **)calloc(n,sizeof(int)*m);
printf("\nEnter the elments: ");
//To access the memory
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",ptr[i][j]);
}
}
Since C99 you can use pointers to VLAs (Variable Length Arrays):
int n, m;
scanf("%d %d", &n, &m);
int (*ptr)[m] = malloc(sizeof(int [n][m]));
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &ptr[i][j]); // Notice the address of operator (&) for scanf
}
}
free(ptr); // Call free only once
If it's just about minimising the number of calls to memory allocation functions you can created such a jagged array like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t n, size_t m)
{
int ** result = NULL;
size_t t = 0;
t += n * sizeof *result;
t += n*m * sizeof **result;
result = calloc(1, t);
if (NULL != result)
{
for (size_t i = 0; i < n; ++i)
{
result[i] = ((int*) (result + n)) + i*m;
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t, size_t);
int main(void)
{
int result = EXIT_SUCCESS;
int ** p = alloc_jagged_2d_array_of_int(2, 3);
if (NULL == p)
{
perror("alloc_jagged_2d_array_of_int() failed");
result = EXIT_FAILURE;
}
else
{
for (size_t i = 0; i < 2; ++i)
{
for (size_t j = 0; j < 3; ++j)
{
p[i][j] = (int) (i*j);
}
}
}
/* Clean up. */
free(p);
return result;
}
I've written a piece of code but I'm not sure about how it works.
I want to create an array of pointers and pass it as argument to a function, like the following:
int main()
{
int *array[10] = {0};
for(int i = 0; i < 3; i++)
{
array[i] = (int *)malloc(3*sizeof(int *));
}
testFunction(array);
for(int i = 0; i < 3; i++)
{
free(array[i]);
}
return 0;
}
void testFunction(int *array[3])
{
//do something
return;
}
What I don't understand is the following. I declare array as an array of pointers, allocate memory to it by using malloc and then proceed to call testFunction. I want to pass the array by reference, and I understand that when I call the function by using testFunction(array), the array decays to a pointer to its first element (which will be a pointer also). But why in the parameters list I have to write (int *array[3]) with * and not just (int array[3])?
A parameter of type * can accept an argument of type [], but not anything in type.
If you write void testFunction(int arg[3]) it's fine, but you won't be able to access array[1] and array[2] and so on, only the first 3 elements of where array[0] points to. Also a comversion is required (call with testFunction((int*)array);.
As a good practice, it's necessary to make the function parametera consistent with what's passed as arguments. So int *array[10] can be passed to f(int **arg) or f(int *arg[]), but neither f(int *arg) nor f(int arg[]).
void testFunction(int **array, int int_arr_size, int size_of_array_of_pointers)
{
for(int j = 0; j < size_of_array_of_pointers; j++)
{
int *arrptr = array[j]; // this pointer only to understand the idea.
for(int i = 0; i < int_arr_size; i++)
{
arrptr[i] = i + 1;
}
}
}
and
int main()
{
int *array[10];
for(int i = 0; i < sizeof(array) / sizeof(int *); i++)
{
array[i] = malloc(3*sizeof(int));
}
testFunction(array, 3, sizeof(array) / sizeof(int *));
for(int i = 0; i < sizeof(array) / sizeof(int *); i++)
{
free(array[i]);
}
return 0;
}
Evering depends on what // do something means in your case.
Let's start from simple : perhaps, you need just array of integers
If your function change only values in array but does not change size, you can pass it as int *array or int array[3].
int *array[3] allows to work only with arrays of size 3, but if you can works with any arrays of int option int *array require additional argument int size:
void testFunction(int *array, int arr_size)
{
int i;
for(i = 0; i < arr_size; i++)
{
array[i] = i + 1;
}
return;
}
Next : if array of pointers are needed
Argument should be int *array[3] or better int **array (pointer to pointer).
Looking at the initialization loop (I changed sizeof(int *) to sizeof(int))
for(int i = 0; i < 3; i++)
{
array[i] = (int *)malloc(3*sizeof(int));
}
I suppose you need 2-dimension array, so you can pass int **array but with sizes of two dimensions or one size for case of square matrix (height equal to width):
void testFunction(int **array, int wSize, int hSize)
{
int row, col;
for(row = 0; row < hSize; row++)
{
for(col = 0; col < wSize; col++)
{
array[row][col] = row * col;
}
}
}
And finally : memory allocation for 2D-array
Consider the following variant of your main:
int main()
{
int **array;
// allocate memory for 3 pointers int*
array = (int *)malloc(3*sizeof(int *));
if(array == NULL)
return 1; // stop the program
// then init these 3 pointers with addreses for 3 int
for(int i = 0; i < 3; i++)
{
array[i] = (int *)malloc(3*sizeof(int));
if(array[i] == NULL) return 1;
}
testFunction(array, 3, 3);
// First, free memory allocated for int
for(int i = 0; i < 3; i++)
{
free(array[i]);
}
// then free memory allocated for pointers
free(array);
return 0;
}
Pay attention, that value returned by malloc should be checked before usage (NULL means memory was not allocated).
For the same reasons check can be added inside function:
void testFunction(int **array, int wSize, int hSize)
{
int row, col;
if(array == NULL) // check here
return;
for(row = 0; row < hSize; row++)
{
if(array[row] == NULL) // and here
return;
for(col = 0; col < wSize; col++)
{
array[row][col] = row * col;
}
}
}
Hi, I'm a newbie in C (and in programming) and I'm trying to make a function that returns dynamically allocated array. It looks like:
int *returnArray(void)
{
int i, *p[4];
for (i = 0; i < 4; i++)
if ((p[i]=(int *)malloc(sizeof(int)*(4-i))) == NULL)
return NULL;
return &p[0][0];
}
And calling to this function:
int *ar;
if ((ar = returnArray()) == NULL) {
/* ERROR */
return 1;
}
But it doesn't work at all. After calling the function I wish to use *ar like a normal 2D array + unallocate the memory at the end of programme. Even if I've looked at similar topics I don't know how to fix it.
Thank you all for your help. I understand it much better now.
You're close. What you are missing is that you need to allocate both dimensions, like this:
int** CreateTwoDimensionalArray(int rows, int cols)
{
int row, prevrow;
int** result = (int**) calloc(rows, sizeof(int*));
if (result == NULL) {
return NULL;
}
for (row = 0; row < rows; ++row) {
int* current_row = (int*) calloc(cols, sizeof(int));
if (current_row == NULL) {
for (prevrow = 0; prevrow < row; ++prevrow) {
free(result[prevrow]);
}
free(result);
return NULL;
}
result[row] = current_row;
}
return result;
}
void FreeTwoDimensionalArray(int** array, int rows, int cols)
{
int row;
for (row = 0; row < rows; ++row) {
free(array[row]);
}
free(array);
}
In function returnArray, variable p is a local variable, so you should not return its address.
You can return one of the values in it (for example - p[2]), but you will obviously lose all the others.
So instead of returning this array, pass it to the function and initialize the entries inside:
void initArray(int* p[])
{
int i;
for (i=0; i<SIZE; i++)
p[i] = (int*)malloc(sizeof(int)*(SIZE-i));
}
Then, you can call this function and check if all allocations have completed successfully:
int i;
int* p[SIZE];
initArray(p);
for (i=0; i<SIZE; i++)
{
if (p[i] == NULL)
break;
}
if (i < SIZE)
{
//Error - not all allocations have completed successfully
}
else
{
// Example #1
scanf("%d",&p[3][0]);
printf("%d",p[3][0]);
// Example #2
scanf("%d" , p[3]);
printf("%d",*p[3]);
}
And of course, you will need to release the allocated memory at a later point in execution:
void freeArray(int* p[])
{
int i;
for (i=0; i<SIZE; i++)
{
if (p[i])
free(p[i]);
}
}
Okay so I'm trying to pass elements of a 2D array with string elements to a 2D array in struct. I made a code, but it receives a run-time error. I think there's a problem in the code where I'm trying to initialize board2[i][j]. Any help is appreciated.
char ***board;
int i, j, size;
printf("Enter the size of array:");
scanf("%d", &size);
if((board = (char***)malloc(sizeof(char**)*size))==NULL)
{
printf("Memory Allocation failed\n");
return -1;
}
for(i=0; i<size; i++)
{
if((board[i] = (char**)malloc(sizeof(char*)*size))==NULL)
{
printf("Memory Allocation failed\n");
return -1;
}
for(j=0; j<size; j++)
{
if((board[i][j] = (char *)malloc(sizeof(char)*4))==NULL)
{
printf("Memory Allocation failed\n");
return -1;
}
a = rand() % 2;
b = rand() % 2;
if(a==0 && b==0)
strcpy(board[i][j], "ab");
else if(a && b==0)
strcpy(board[i][j], "Ab");
else if(a==0 && b==1)
strcpy(board[i][j], "aB");
else
strcpy(board[i][j], "AB");
}
struct data{
const char *element;
int visited;
};
void board2_initialize(char ***board, int size)
{
struct data **board2;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
board2[i][j].element = board[i][j];
board2[i][j].visited = 0;
printf("%s", board2[i][j].element);
}
}
}
EDIT: Forgot to mention that the initialization will occur inside a function
You allocate it just the same way you do the board arrays:
struct data **board2 = malloc(sizeof(struct data *) * size);
for(i = 0; i < size; i++)
{
board2[i] = malloc(sizeof(struct data) * size);
for(j = 0; j < size; j++)
{
/* ... */
}
}