C - create an array with malloc, then loop through it - c

I'm learning C at the moment and tried to write this function
int *create_matrix(int n) {
int *matrix = malloc(n*n*sizeof(int));
srand(time(NULL));
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
matrix[i][j] = rand()%10;
}
}
return matrix;
}
why does this fail to compile? its complaining about matrix[i][j] is not an pointer/array. but I've just declared it as an pointer six lines above...

It's a 1D array, so you have to treat it as a 1D array, and not as 2D.
You can of course still store your n x n elements in it:
matrix[i * n + j] = rand() % 10;
If you prefer, you can set up a 2D structure by following the advice given in How do I work with dynamic multi-dimensional arrays in C?
By the way, you probably don't want to be calling srand() every time you create a matrix. If you call create_matrix() twice in quick succession, you could end up getting the same "random" matrix. Call srand() once at the start of your program.

You've declared matrix as a one-dimensional array, and not as a two-dimensional array.
So use it like:
for(int i=0; i<n*n; ++i)
matrix[i] = //whatever;
If you really need two-dimensional array, you need to use double pointers:
int **matrix = malloc(n * sizeof(int *)); // notice the double pointer
// ....
// ....
for (i = 0; i < n; i++)
{
matrix[i] = malloc(sizeof(int) * n);
// ....
}

You declare matrix as a one-dimensional array. You need to either store the data in it as such, i.e.
matrix[i * n + j] = rand() % 10;
Or declare it as a two-dimensional array and allocate memory accordingly.
int** matrix = malloc(n * sizeof(int*));
int i, j;
for (i = 0; i < n; i++) {
matrix[i] = malloc(n * sizeof(int));
for (j = 0; j < n; j++) {
matrix[i][j] = rand() % 10;
}
}

What it's really complaining about is, the matrix[i] is not a pointer/array. You've only created a 1-dimensional array, you either can access it directly like
matrix[i * n + j] = rand() % 10;
or go ahead, do it cleanly, and redo the array, so it will be 2-dimensional. You'll need to use pointer to a pointer (for every member in line - one row)
int **matrix
but you'll have to loop trough the
*matrix
to malloc each row by itself.
Look up on 2-dimensional arrays.
//EDIT: Also, move the srand() to the beginning of the file. You don't want to srand() with every new matrix.

You want two dimensions, then you need a pointer to pointer (not a single pointer):
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int **create_matrix(int n)
{
int **matrix = malloc(n * sizeof(int *));
srand(time(NULL));
int i, j;
for (i = 0; i < n; i++) {
matrix[i] = malloc(sizeof(int) * n);
for (j = 0; j < n; j++) {
matrix[i][j] = rand()%10;
}
}
return matrix;
}
int main(void)
{
int **matrix = create_matrix(5);
return 0;
}

Related

Dynamic memory allocation for two-dimensional arrays

I want to allocate memory for a two-dimensional array (matrix) and write the sums of the diagonals in a separate one-dimensional array. So my code has an array of pointers to pointers,
int N, ** matrix = NULL;
matrix = (int**) malloc(sizeof(int*) * N);
I fill it and then I create an array to store the sums of the diagonals,
int diag = 2 * N - 1;
int *diagonals = NULL;
diagonals = (int*)malloc(sizeof(int) * diag);
but when I want to write a value into an array, something goes wrong, the values just don't get written into the array; I don't know why.
Here is my code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main() {
srand(time(NULL));
int N, ** matrix = NULL;
printf("Input the number of rows\n");
scanf_s("%d", &N);
printf("\n");
// Memory allocation for the array of pointers to pointers
matrix = (int**) malloc(sizeof(int*) * N);
if (matrix != NULL)
{
for (int i = 0; i < N; i++)
*(matrix + i) = (int*)malloc(sizeof(int) * N);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
matrix[i][j] = rand() % 14 - 4;
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
printf("\n");
int diag = 2 * N - 1;
int *diagonals = NULL;
diagonals = (int*)malloc(sizeof(int) * diag);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
diagonals[i+j] += matrix[i][j];;
}
}
for (int i = 0; i < diag; i++) {
printf("diagonals[%d] - %d\n",i, *(diagonals+i));
}
}
else
printf("Not enough memory.. oops..\n");
}
The content of diagonals is allocated with malloc() which does not initialize the memory. You should use calloc() which initializes the memory with zeros:
diagonals = calloc(diag, sizeof *diagonals);
The following loop assumes that each element of diagonals was initialized to zero, but you performed no such initialization. As a result, they are uninitialized and will contain whatever value happens to be sitting in the newly-allocated memory.
diagonals = malloc(sizeof(int) * diag);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
diagonals[i+j] += matrix[i][j];;
}
}
You have several options for zero-initialization:
Use memset to zero the memory, after allocation:
diagonals = malloc(sizeof(int) * diag);
memset(diagonals, 0, sizeof(int) * diag);
Initialize values in a loop:
diagonals = malloc(sizeof(int) * diag);
for (int i = 0; i < diag; i++) diagonals[i] = 0;
Allocate with calloc:
diagonals = calloc(diag, sizeof(int));
Note that in all cases, you should be checking the result of allocation. If it fails and returns NULL, you should not attempt to access memory via that pointer.
It does not answer the question but I would suggest using real 2D arrays instead of arrays of pointers. To dynamically allocate the 2D array you need to use a pointer to array.
int (*matrix)[N] = malloc(N * sizeof(*matrix));
You will have only one allocation and one free. Fever levels of indirection.

How can I create a matrix in a void function and return as parameter C

I have to create a matrix but with the following requirements:
create a function for it
the matrix has to be dynamic allocated inside the function
the matrix has to be returned as a parameter of the function (function has to be void)
What I tried:
void createMatrix(int n,float** matrix)
{
matrix = (float**)malloc(n * sizeof(float*));
for (int i = 0; i < n; i++)
matrix[i] = (float*)malloc(n* sizeof(float));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
matrix[i][j] = 0;
}
int main()
{
int n;
FILE* fis;
fis = fopen("fileIn.txt", "r");
if (!fis)
{
printf("File not opened");
return;
}
fscanf(fis, "%d", &n);
fclose(fis);
float** matrix;
createMatrix(n, &matrix);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf("%f ", matrix[i][j]);
printf("\n");
}
return;
}
If you're passing the address of a float ** to a function, the type of the parameter should be float ***. So in the function, change the parameter type to that and use *matrix wherever matrix was used.
void createMatrix(int n, float ***matrix)
{
*matrix = malloc(n * sizeof(float*));
for (int i = 0; i < n; i++)
(*matrix)[i] = malloc(n* sizeof(float));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
(*matrix)[i][j] = 0;
}
Note that the casts have also been removed, as casting the return value of malloc is not necessary and can mask other errors in your code.
You also should add error checking after the calls to malloc.
If you are creating the matrix such a way
matrix = (float**)malloc(n * sizeof(float*));
for (int i = 0; i < n; i++)
matrix[i] = (float*)malloc(n* sizeof(float));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
matrix[i][j] = 0;
and want to return the matrix through a parameter then the function should be declared like
void createMatrix( int n, float ***matrix )
{
*matrix = malloc( n * sizeof( float* ) );
for ( int i = 0; i < n; i++ )
( *matrix )[i] = malloc( n * sizeof( float ) );
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < n; j++ )
{
( *matrix )[i][j] = 0;
}
}
}
That is if you are passing the pointer matrix declared in main like
float** matrix;
to the function by reference through a pointer to it
createMatrix(n, &matrix);
then the corresponding function parameter will have the type float ***.
You'll need to change createMatrix as follows:
void createMatrix(int n,float*** matrix)
{
*matrix = (float**)calloc(n,sizeof(float*));
for (int i = 0; i < n; i++)
*matrix[i] = (float*)calloc(n,sizeof(float));
}
In order for the caller to be able to see the matrix you create, you have to pass a pointer to it... yes, that is a pointer-to-a-pointer-to-a-pointer. And by using calloc instead of malloc, the initialization to zero is handled for you.
Some things to note:
Your function is creating a pointer-to-pointer look-up table, not a 2D array. Pointer-to-pointer look-up tables only make sense when we want individually-sized items, which is never the case in a mathematical, square-shaped matrix. All the pointer-to-pointer trick achieves is bloat, slow access and needless complexity. You gain absolutely no advantages from it. For details see Correctly allocating multi-dimensional arrays
This look-up table is assigned to the local variable matrix and not returned from the function, which is a bug and a memory leak.
We can easily fix these bugs and design mistakes if you can drop those requirements you listed. Then there's a much better standard C function for all of this called calloc.
Usage:
size_t fx = 5;
size_t fy = 3;
float (*fmat)[fy] = calloc( 1, sizeof(float[fx][fy]) );
...
free(fmat);
This is much faster than your function, it doesn't come with needless type-generic programming, it allocates a true 2D array in contiguous memory which gives data cache coherence and it sets all data items to zero.

C Language, dynamic 3d array

I have to create a dynamic and 3 dimensional integer-Array in C.
But I have to create the pointers separately and use malloc. I know how to create 2d Array with malloc but I get confused using the following method, and i couldn't really find other question similar to this.
2x2x2 Integer-Array
First step:
int *firstD;
firstD = (int) malloc(2*sizeof(int));
Second step:
int *secondD;
secondD = (int) malloc(2 * firstD * sizeof(int));
Third step:
int *thirdD;
thirdD = (int) malloc(2 * secondD * sizeof(int));
I think maybe I have to add pointers in the starting (int*) and increase it every stepp by one more pointer?
Allocate an array to store pointers to arrays of row pointers.
Allocate arrays to store row pointers.
Allocate arrays to store each rows.
#include <stdlib.h>
int main(void) {
int size1 = 2, size2 = 2, size3 = 2;
int*** array;
array = malloc(sizeof(int**) * size1); // 1
for (int i = 0; i < size1; i++) {
array[i] = malloc(sizeof(int*) * size2); // 2
for (int j = 0; j < size2; j++) {
array[i][j] = malloc(sizeof(int) * size3); // 3
}
}
// free arrays
for (int i = 0; i < size1; i++) {
for (int j = 0; j < size2; j++) {
free(array[i][j]);
}
free(array[i]);
}
free(array);
return 0;
}
I wrote type names explicitly in the above example, but I suggest using dereferencing to obtain size of elements to allocate is better to prevent causing typos.
#include <stdlib.h>
int main(void) {
int size1 = 2, size2 = 2, size3 = 2;
int*** array;
// allocate arrays
array = malloc(sizeof(*array) * size1); // 1
for (int i = 0; i < size1; i++) {
array[i] = malloc(sizeof(*array[i]) * size2); // 2
for (int j = 0; j < size2; j++) {
array[i][j] = malloc(sizeof(*array[i][j]) * size3); // 3
}
}
// free arrays
for (int i = 0; i < size1; i++) {
for (int j = 0; j < size2; j++) {
free(array[i][j]);
}
free(array[i]);
}
free(array);
return 0;
}
Onitted in the above examples to make them simple, but you should check results of malloc() to see if the allocations are successful.

Understanding Array of pointers

I am doing something like this;
int main()
{
int *b[2], j;
for (j = 0; j < 2; j++)
{
b[j] = (int *)malloc(12 * sizeof(int));
}
return 0;
}
Please tell me what this instruction really means? And how can I pass this array of pointers to a function to access values like *(B[0]+1),*(B[1]+1) etc?
int main(void)
{
int *b[2], j; // initialization of an array of pointers to integers (size = 2)
for (j = 0; j < 2; j++) // for each of the pointers
{
b[j] = malloc(12 * sizeof (int)); // allocate some space = 12 times size of integer in bytes (usually 4)
}
return 0;
}
If you want to pass this array to a function you can just pass b
foo(b);

C: Matrix multiplication using double pointers

I've been given a code that reads in the matrix from two text files. (Assuming that is correct) I need to come up with a function that multiples two matrices together.
This is the given function prototype:
int** matMult(int **a, int num_rows_a, int num_cols_a, int** b, int num_rows_b, int num_cols_b);
And here is my code for the function:
int** matMult(int **a, int num_rows_a, int num_cols_a, int** b, int num_rows_b, int num_cols_b){
int **c;
c = (int**)malloc(sizeof(int*)*num_rows_a);
// c = calloc(num_rows_a, num_cols_b);
for (int i = 0; i < num_rows_a; i++) {
for (int j = 0; j < num_cols_b; j++) {
int sum = 0;
for (int k = 0; k < num_cols_a; k++) {
c[i][j] = a[i][k] * b[k][j] + sum;
sum = c[i][j]; //so that previous answer gets stored
}
}
}
return c;
}
I have to call malloc to allocate space for the resulting matrix, c
Also the issue I'm getting from Xcode is : EXC_BAD_ACCESS
You need to allocate memory for columns too. :
int **c;
c = (int**)malloc(sizeof(int*)*num_rows_a);
for(i=0;i<num_rows_a;i++)
c[i]=malloc(sizeof(int)*num_cols_b);
The answer by #Stinson addresses the memory problem already. I'm going to suggest a little refinement of the inner block of code. There is no need to have temporary sum in the code.
for (int i = 0; i < num_rows_a; i++) {
c[i] = malloc(sizeof(int)*num_cols_b);
for (int j = 0; j < num_cols_b; j++) {
// Initialize the element to zero.
c[i][j] = 0;
for (int k = 0; k < num_cols_a; k++) {
// Accumulate the result
c[i][j] += a[i][k] * b[k][j];
}
}
}

Resources