0

I'm trying to dynamically allocate memory to a 2d array using a single pointer. For that, I have 3 functions that allocate the respective memory newarray() and to store individual elements in it store(), to fetch elements from it fetch(). I don't know why I get execution errors while I test it, also I should allocate the the exact amount of memory for it, that might be the problem but I'm not sure how to do that. This probrams deals with a triangular matrix which should have the number of columns lower than the number of rows when It comes to adding elements, like I, have a 5x5 array where (4,2) and (4,4) its OK but (4,5) its NOT.

Here is the code


typedef int* triangular;

triangular newarray(int N){
    triangular mat = NULL; //pointer to integer
    //Allocate memory for row
    mat = (int *)malloc(N * N * sizeof(int));
    //Check memory validity
    if(mat == NULL)
    {
        return 1;
    }

    return mat;
}

int store(triangular as, int N, int row, int col, int val){
    if(row >= col){
        as[row * N + col] = val;
        return 1;
    }else if(row < col){
        return -1;
    }else if((row > N) ||(col > N) || (row + col > N + N))
        return -1;
}

int fetch(triangular as, int N, int row, int col){
    int value;
    value = as[row * N + col];
    if((row > N) ||(col > N) || (row + col > N + N) )
        return -1;
    else if(row < col)
        return -1;
    return value;
}

nt main()
{
    int iRow = 0; //Variable for looping Row
    int iCol = 0; //Variable for looping column
    int N;
    triangular mat = newarray(5);

    printf("\nEnter the number of rows and columns = ");
    scanf("%d",&N); //Get input for number of Row

    store(mat,N,3,2,10);
    store(mat,N,3,3,10);
     store(mat,N,4,2,111);
    store(mat,N,3,5,11);
    printf("the element at [3,5] is : %i", fetch(mat,N,3,5));
    //Print the content of 2D array

     for (iRow =0 ; iRow < N ; iRow++)
    {
        for (iCol =0 ; iCol < N ; iCol++)
        {
            printf("\nmat[%d][%d] = %d\n",iRow, iCol,mat[iRow * N + iCol]);
        }
    }

    //free the allocated memory
    free(mat);

    return 0;
}


marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Bella James
  • 39
  • 1
  • 8
  • 1
    `if(mat == NULL) { return 1; }`? Wouldn't it be better to `return NULL` in that case? – Some programmer dude Jun 04 '21 at 12:04
  • As for your problem, you do remember that array indexing is *zero* based? Which means index `5` (for either row or column) will be out of bounds for a `5x5` matrix. – Some programmer dude Jun 04 '21 at 12:05
  • i think so but should no be the issues , I think I allocated space for all the array, I think I need to allocate space for the exact elements I'm adding or something – Bella James Jun 04 '21 at 12:05
  • Please also include code that uses these functions, as their error-checking is not water-tight. – unwind Jun 04 '21 at 12:05
  • The 3rd `if` statement in `store` can never be executed. In `fetch`, you read the memory before checking bounds - that results in undefined behavior. (You also don't check negative indexes, which can also result in out-of-bounds accesses). – Paul Hankin Jun 04 '21 at 12:06
  • still not sure what to do tbh, first time I'm using pointers for such implementaion – Bella James Jun 04 '21 at 12:06
  • just included the main function which takes the code – Bella James Jun 04 '21 at 12:07
  • it looks right when i test it but I get execution errors when it comes to feedback by the system – Bella James Jun 04 '21 at 12:08
  • `store(mat,N,3,5,11)` Here the index `5` will be out of bounds. Same when you call `fetch(mat,N,3,5)`. Furthermore, you don't initialize all of the memory you allocate, which means most of the memory will be uninitialized and have *indeterminate* values (which you should consider garbage). – Some programmer dude Jun 04 '21 at 12:10
  • On the other hand the `store` function have the condition `if(row >= col)` to set a value, and since `3 >= 5` will be false then you won't actually write anything in the case of `store(mat,N,3,5,11)` – Some programmer dude Jun 04 '21 at 12:12
  • how should i fix this , because I'm still not entirely sure how to do that, now I've added more conditions to it to check negative values as well but not sure about the index out of bound and allocating issues – Bella James Jun 04 '21 at 12:13
  • store(mat,N,3,5,11) this last one was deliberately set by me to check if the return errors works – Bella James Jun 04 '21 at 12:15
  • Please take some time to sit down with a pen and a piece of paper, and think about it logically. First of all, if you have a matrix of `N x N` then all indexes (`row` and `col`) must be in the range of `0` to `N - 1`. Incorporate that check first. If the indexes are in the valid range then read from the memory, or write to the memory. – Some programmer dude Jun 04 '21 at 12:16
  • did that , is there anything about the newarray() function which I should consider – Bella James Jun 04 '21 at 12:24
  • so now things should work properly? – Bella James Jun 04 '21 at 12:28
  • Never hide pointers behind typedef. You will only end up fooling yourself and everyone else reading the code. – Lundin Jun 04 '21 at 12:47
  • it it an online exercise , which required me to use a typedef for it – Bella James Jun 04 '21 at 12:50
  • im not sure how to allocate the exact space for the matrix , because now I'm doing NxN matrix – Bella James Jun 04 '21 at 12:51
  • for (i=0; i – Bella James Jun 04 '21 at 12:51
  • would this work – Bella James Jun 04 '21 at 12:51
  • I never used pointers, nor i ever used c language, i know its an easy fix thing but due to these reasons I cannot figure this out , I mostly learn from direct examples and I tried to look for a way to do this everywhere but did not find any useful information – Bella James Jun 04 '21 at 13:06
  • Okay. And I've used pointers for several decades. So when I tell you that hiding them behind a typedef is a bad idea, can't you just take my word for it? It sounds like you are learning from a bad source. There are many bad and harmful tutorials out there. – Lundin Jun 04 '21 at 13:22

2 Answers2

0
int store(triangular as, int N, int row, int col, int val){
    if(row >= col){
        as[row * N + col] = val;
        return 1;
    }else if(row < col){
        return -1;
    }else if((row > N) ||(col > N) || (row + col > N + N))
        return -1;
}

in store function, first if condition is so weird. Why you dont set the value to the array when the parameters passed to function is 2(row), 3(column).

I changed your store in the following way. index and array size are different things because of that index is equal to N - 1. In your code, there are a lot of if checks I guess checking only row and col is enough to understand that they are inside boundaries.

int store(triangular as, int N, int row, int col, int val){
    int index = N - 1;

    if((row > N) ||(col > N))
        return -1;

    as[row * index + col] = val;

    return 1;
}

I changed your fetch function like below because the reason I mentioned about your store function.

int fetch(triangular as, int N, int row, int col){
    int value;
    int index = N - 1;
    
   if((row > index) ||(col > index))
        return -1;
   
   value = as[row * index + col];
    
    return value;
}
  • You check the bounds *after* you store the value (and possibly going out of bounds). Those operations needs to happen in the opposite order. The bounds-checking is wrong as well, as `N` is an invalid index and your check allows it. – Some programmer dude Jun 04 '21 at 12:52
  • `int store(triangular as, int N, int row, int col, int val){ if(row >= col && row <= N-1 && col <= N-1 && row >= 0 && col >= 0){ as[row * N + col] = val; return 1; }else if(row < col){ return -1; }else if((row > N-1) ||(col > N-1) || (row + col > (N-1) + (N-1)) return -1; else if(row < 0 || col < 0 || (row < 0 && col < 0)) return -1; } ` – Bella James Jun 04 '21 at 12:54
  • i placed the check at the beginning of store and fetch – Bella James Jun 04 '21 at 12:55
  • `for (i=0; i – Bella James Jun 04 '21 at 12:55
  • would this work for just allocating memory for the rows and cols i need for the triangle matrix – Bella James Jun 04 '21 at 12:56
  • @StoicaRobert Your checks are too complicated. `if (row < 0 || row >= N || col < 0 || col >= N)` is enough to check for invalid indexes for `row` and `col`. – Some programmer dude Jun 04 '21 at 12:56
  • @StoicaRobert, your memory allocation is correct. why you think it is wrong ? – beginner_dv Jun 04 '21 at 12:57
  • i think im allocating N * N space but the problem condition ask me to allocate the exact space needed for the triangle matrix – Bella James Jun 04 '21 at 12:59
  • I guess you cannot get the exact space needed for the triangle matrix using memory allocation functions because they gets chunks from the system memory not the exact space that user wants to get and those chunks are always bigger than your request. – beginner_dv Jun 04 '21 at 13:07
  • @StoicaRobert For an NxN matrix of `int` values you're allocating correctly. – Some programmer dude Jun 04 '21 at 15:35
  • @StoicaRobert Note that while you allocate it correctly, you don't initialize the memory. Either use [`calloc`](https://en.cppreference.com/w/c/memory/calloc) to allocate zero-initialized memory, or use [`memset`](https://en.cppreference.com/w/c/string/byte/memset) to initialize after `malloc`. – Some programmer dude Jun 04 '21 at 19:12
0

You are making this needlessly complicated. All those functions and manual run-time calculations aren't really necessary.

Also, you have the following problems:

  • Don't hide pointers behind typedef, it just makes the code unreadable for no gain.
  • Initialize the data returned from malloc or instead use calloc which sets everything to zero, unlike malloc.
  • Arrays in C are zero-indexed so you can't access item [3][5] in an array of size 5x5. This is a common beginner problem since int array[5][5]; declares such an array but array[5][5] for index accessing goes out of bounds. The syntax for declaration and access isn't the same, access needs to start at 0.
  • You didn't include any headers, I'm assuming you left that part out.

Here's a simplified version with bug fixes that you can use:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  int N=5;
  int (*mat)[N] = calloc( 1, sizeof(int[N][N]) ); // allocate 2D array dynamically
  if(mat == NULL)
    return 0;

  mat[3][2] = 10;
  mat[3][3] = 10;
  mat[4][2] = 111;
  mat[3][4] = 11;

  for(int i=0; i<N; i++)
  {
    for(int j=0; j<N; j++)
    {
      printf("[%d][%d] = %d\n", i, j, mat[i][j]);
    }
  }

  free(mat);
  return 0;
}

Further study: Correctly allocating multi-dimensional arrays

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • the issue is that I'm required to use this set up , malloc and typedef as this is an online exercise , also Im not entirely sure how to allocate the exact space for the matrix , as now I'm allocating all the space for it NxN – Bella James Jun 04 '21 at 13:10