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.
Related
I have to calculate the speed of operation for different threads but the matrix size has to be (1000X1 and 1X1000). I have to calculate this using 1,2,4,8,16,32,64,128,256 and 512 threads.
my program is returning same values for all the resultant matrix. Where do I make changes?
I am using random number generator to fill the matrices and dynamically allocating and freeing the matrices.
I first kept N = 512 but I was getting segmentation fault core dumped error so I increased the N. How can I use different number of threads to calculate the matrix?
For a 1000X1 and 1X1000 matrix the resulatant matrix is all 18 and gets segmentation fault core dump error.
For 100X1 and 1X100 all values are 3 and the same happens
to compile it you have to use -lpthreads and -fopenmp
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
// Each thread computes single element in the resultant matrix
void *mult(void *arg)
{
int *data = (int *)arg;
int k = 0, i = 0;
int x = data[0];
for (i = 1; i <= x; i++)
k += data[i] * data[i + x];
int *p = (int *)malloc(sizeof(int));
*p = k;
// Used to terminate a thread and the return value is passed as a pointer
pthread_exit(p);
}
// Driver code
int main()
{
int i, j, k, row1, col1, row2, col2, r, sum, no_of_threads;
printf("Enter the number of rows for matrix 1\n");
scanf("%d", &row1);
printf("Enter the number of columns for matrix 1 \n");
scanf("%d", &col1);
printf("Enter the number of rows for matrix 2 \n");
scanf("%d", &row2);
printf("Enter the number of columns for matrix 2\n");
scanf("%d", &col2);
int **a = (int **)malloc(row1 * sizeof(int *));
for (i = 0; i < row1; i++)
a[i] = (int *)malloc(col1 * sizeof(int));
int **b = (int **)malloc(row2 * sizeof(int *));
for (i = 0; i < row2; i++)
b[i] = (int *)malloc(col2 * sizeof(int));
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
{
a[i][j] = (rand() % 9) + 1;
}
}
for (i = 0; i < row2; i++)
{
for (j = 0; j < col2; j++)
{
b[i][j] = (rand() % 9) + 1;
}
}
int N = 1000;
// declaring array of threads of size row1*col2
pthread_t *threads;
threads = (pthread_t *)malloc(N * sizeof(pthread_t));
int count = 0;
int *data = NULL;
for (i = 0; i < row1; i++)
for (j = 0; j < col2; j++)
{
// storing row and column elements in data
data = (int *)malloc((N) * sizeof(int));
data[0] = col1;
for (k = 0; k < col1; k++)
data[k + 1] = a[i][k];
for (k = 0; k < row2; k++)
data[k + col1 + 1] = b[k][j];
}
// creating threads
for (int i = 0; i < 512; i++)
{
std:
pthread_create(&threads[i], NULL,
mult, (void *)(data));
}
printf("RESULTANT MATRIX IS :- \n");
for (i = 0; i < N; i++)
{
void *k;
// Joining all threads and collecting return value
pthread_join(threads[i], &k);
int *p = (int *)k;
printf("%d ", *p);
if ((i + 1) % col2 == 0)
printf("\n");
}
for (int i = 0; i < row1; i++)
{
free(a[i]);
}
for (int i = 0; i < row2; i++)
{
free(b[i]);
}
free(a);
free(b);
free(data);
return 0;
}
EDIT:
How do I send multiple arguments through threads as if I read the matrix in my main function, I am not able to pass the values of rows and columns to my mult function. If I read the matrix in mult function then the threads are not working. How do I get it to multiply?
Your approach is flawed:
the destination matrix is not allocated properly
you pass the same argument to all threads
the threads do not receive any information regarding where to store the result of the scalar product.
You should allocate an argument structure for each thread and pass the source arrays and destination location.
With the current approach, there are row1 * col2 scalar products to compute: if you want to use fixed number of threads, you should construct a list of tasks for each thread to process in order to distribute the word among the threads. It is rather easy to do it statically and since all single computations are equivalent in terms of complexity, dynamic distribution does not seem necessary.
Note however that you must wait for all threads to complete before examining and freeing the results. Freeing the arrays as the threads are potentially still accessing the data is among the many causes for undefined behavior in the posted code.
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.
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;
}
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);
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;
}