0

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.

enter image description here

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");
}
10
  • 1
    *(matrix + i) is a really smug way of writing matrix[i], IMO. Commented Nov 29, 2022 at 22:16
  • 5
    You did not initialize values in the diagonals array before the loops. Those loops use += to modify the existing value. You're clearly assuming the values start off initially as zero, but they are uninitialized. You must initialize them explicitly with a loop, or memset, or allocate with calloc. Commented Nov 29, 2022 at 22:16
  • 2
    And since this is tagged c, you don't cast the result of malloc. Commented Nov 29, 2022 at 22:17
  • why diags = 2* N - 1 and not 2*N Commented Nov 29, 2022 at 22:18
  • 1
    @DanMašek, maybe, but manual calculations of indices becomes very cumbersome for 3D and more tensors. VLA types were introduced to make handling such entities much easier. Commented Nov 29, 2022 at 22:45

3 Answers 3

2

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);
Sign up to request clarification or add additional context in comments.

Comments

2

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:

  1. Use memset to zero the memory, after allocation:

     diagonals = malloc(sizeof(int) * diag);
     memset(diagonals, 0, sizeof(int) * diag);
    
  2. Initialize values in a loop:

     diagonals = malloc(sizeof(int) * diag);
     for (int i = 0; i < diag; i++) diagonals[i] = 0;
    
  3. 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.

Comments

0

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.

5 Comments

The use of VLA should include a test for availability, since its support is optional in C.2011 and above. See: stackoverflow.com/questions/49988521/…
@jxh, support for VLA typew is going to be mandatory in C23. There will be no need for this check anymore
@tstanisl The references I have found refer to variably-modified types being mandatory, not VLA. Is that what you meant?
@jxh, VLA means an object of "VLA type" which is a subtype of VMT family. In C23 one can create any VLA type: typedef int T[n];. However, only creation of an object of VLA type with automatic storage are going to be optional. So T a; will be optional while support for T *a = malloc(sizeof *a); will be mandatory.
@tstanisl VLA means an object of "VLA type" -- got it, thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.