0

The Question asks the User to input a 2D array whose no. of rows are fixed (take rows = 3) and no. of columns are given by the User as follows:

Input:
2 1 2
4 10 20 30 40
5 6 7 8 9 0

Here in the first line 2 1 2, first input tells about the no. of columns in the row index [0] and rest of input are values for row index [0]. And so on for the rest of the lines.
Then, the User enters the row and column index and prints the respective value.
Input: 1 2
Output: 30

I solved it using the array of pointers as:

#include <stdio.h>

int main()
{
  
    int a, c;
    int x , y;   // index coordinates
    
    int *pa[3];
    pa[0] = &a;
    
    for (int i = 0; i < 3; i++)
    {
        if(i != 0) 
            pa[i] = pa[i-1] + c;   //point to mem address c*sizeof(int) bytes away from prev pointer
        
        scanf("%d", &c);  //input no. of column for row[i]

        for (int j = 0; j < c; j++)
        {
            int k;
            scanf("%d", &k);
            *(pa[i] + j) = k;
        }
    }
    
    scanf("%d %d", &x, &y);
    printf("--> %d", *(pa[x] + y));
    
    return 0;

This runs correctly on MSVC and Clang but for some reason not on GCC. There is some kind of run-time error during Input in GCC.

PS: I have solved this using dynamic mem allocation but just wanted to know why the above code does not work in case of GCC:

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

int main()
{
    int **data = (int **) malloc(3*sizeof(int*));
    
    for(int i = 0; i < 3; ++i)
    {
        int c;
        scanf("%d", &c);
        data[i] = (int *) malloc(c*sizeof(int));
        for(int j = 0; j < c; ++j)
        {
            int k;
            scanf("%d", &k);
            data[i][j] = k;
        }           
    }
    int i, j;
    scanf("%d %d", &i, &j);
    printf("--> %d", data[i][j]);
    
    for(int i = 0; i < 3; ++i)
        free(data[i]);
    
    free(data);
    return 0;
}

Grey
  • 11
  • 2
  • There is only one `int` at `a`, so `pa[0] = &a;` sets `pa[0]` to point to only one `int`. Whatever memory might happen to be around `a`, it has not been reserved for your use with `a` or `pa`. Then `pa[i] = pa[i-1] + c;` just attempts to set `pa[i]` to point to other places in memory, which also have not been reserved for your use. You cannot just set pointers to whatever addresses you like and use the memory there. – Eric Postpischil Oct 30 '20 at 11:35
  • This is why it seems to work on some compilers: [What is undefined behavior and how does it work?](https://software.codidact.com/questions/277486) – Lundin Oct 30 '20 at 12:37
  • @EricPostpischil so basically setting a new pointer to point at memory location based on another pointer would be UB? It has to be of the form `type* p_var = &var` for memory to be reserved properly. Am I missing something? – Grey Oct 30 '20 at 14:48
  • @Grey: It is fine to set a pointer based on another pointer, such as `x = y + 3;`, where `x` and `y` are pointers. The issue is, what is this actually pointing at? If there are ten objects at `y`, then you can point at `y+3`, because one of them is there. If there is only one object at `y`, then you are not supposed to point at `y+3`, because there is nothing there that has been reserved for you to use. – Eric Postpischil Oct 30 '20 at 14:50

1 Answers1

0

the reason the above code doesn't work in gcc is because when you declare int *pa[3]; you declare an array of 3 pointers to ints. because none of the pointers is dynamically allocated when you try to write to *(pa[i] + j) = k;

but you didn't allocate memory in that index, which is a dereference of the array of pointers (which gives you the pointer in the i position) and then move k * sizeof(int) bytes from that position and dereference that pointer which doesn't belong to you.

Gilad
  • 305
  • 1
  • 2
  • 8