2

The problem is about taking input of a 4X5 matrix and shifting each of its rows circularly left by 2 places. Like if input is {1,2,3,4,5} the output should be {3,4,5,1,2}. I wrote the following code for the same. But I am getting 'segmentation fault(core dumped)' error. Can you help me with this. Also I am a bit susceptible about sending a 2-d array to function with **p argument. DO COMMENT ON THIS ALSO. I want to know why I am getting the error.

#include <stdio.h>
void shift(int **);
int main()
{
    int i,j,a[4][5];
    printf("Enter the elements of the 4X5 matrix:\n");
    for(i=0;i<4;i++)
    {
        for(j=0;j<5;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    printf("Entered Matrix:\n");
    for(i=0;i<4;i++)
    {
        for(j=0;j<5;j++)
        {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    printf("\n");

        shift(a);

        printf("The new array is:\n");
    for(i=0;i<4;i++)
    {
        for(j=0;j<5;j++)
        {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    return 0;
}

void shift(int **p)
{
    int i;
    for(i=0;i<4;i++)
    {
        int temp[2] = {**(p+i),*(*(p+i)+1)};
        *(*(p+i)+0) = *(*(p+i)+2);
        *(*(p+i)+1) = *(*(p+i)+3);
        *(*(p+i)+2) = *(*(p+i)+4);
        *(*(p+i)+3) = temp[0];
        *(*(p+i)+4) = temp[1];
    }
}

Expected Result - Rotated Array Actual Result - Segmentation Fault(Core Dumped)

Sukrit Kapil
  • 103
  • 6
  • Possible duplicate of [How to pass a 2D array by pointer in C?](https://stackoverflow.com/questions/16724368/how-to-pass-a-2d-array-by-pointer-in-c) – O'Neil Jun 05 '19 at 12:18
  • Rather than using nested arrays, a better solution in ~ 99% of cases is to represent a 2D array as an `int*`, and to perform the index computation yourself. All major linear algebra libraries do it that way. – Konrad Rudolph Jun 05 '19 at 12:27
  • You can use `int*` in place of `int [n]` because an array when used in an expression "decays" to a pointer to the first element. The same goes for 2D arrays, they are actually just arrays of arrays. The first element of a 2D array is a 1D array. And so it decays to a pointer to such an array: `int (*)[n]`. That's why you can't use `int**` because it means something else entirely. So you could write the function as `void shift (int (*arr)[5])` but that's quite hard to read. The method shown in the accepted answer is easier to read and completely equivalent. – Lundin Jun 05 '19 at 13:22

1 Answers1

1

Accessing the array elements of a 2D array like that only works for 2D arrays. Instead of declaring it like this:

void shift(int **p)

You should change it to this:

void shift(int p[4][5])

And the same for the prototype of the function. Click here for a demo.

Blaze
  • 16,736
  • 2
  • 25
  • 44
  • Does that make any difference? Also I used the pointer notation so that I can change the value at the addresses using a void function. Fetching the elements using a matrix notation, I can't do much with a void function. – Sukrit Kapil Jun 05 '19 at 12:17
  • @SukritKapil A 2D array doesn't dereference twice – Thomas Jager Jun 05 '19 at 12:21
  • @ThomasJager Actually I did the same question for a 1-D array. Using *p as an argument. Should not **p work the same way for a 2-D array. – Sukrit Kapil Jun 05 '19 at 12:24
  • @SukritKapil it works this way for me this way and also on online OnlineGDB (I added a link to that). `**p` works, but only for jagged arrays, which is when you have an array of pointer pointing to more arrays. – Blaze Jun 05 '19 at 12:28
  • @SukritKapil A double-pointer could be used as an array of pointers, which you could index into twice. However, a double-pointer is different. The compiler knows that doing `[2][3]` on an `int **` is completely different from doing it on an `int [4][5]`. The former will add `2 * sizeof(int *)` to the pointer address, get the `int *` at that address, add `3 * sizeof(int)` to that address, and get the `int` there. The latter will effectively dereference an `int *` with an index dependant on the indices used, and the size of all but one dimension. – Thomas Jager Jun 05 '19 at 12:29
  • @Blaze Thank you so much. It actually worked. Can you please help me why **p won't work? – Sukrit Kapil Jun 05 '19 at 12:30
  • @SukritKapil Thomas summed that up very well. If you want to do `**p`, you'll need a jagged array, which is explained here: https://stackoverflow.com/a/1083681/10411602 – Blaze Jun 05 '19 at 12:33
  • Thanks to all. Understood. – Sukrit Kapil Jun 05 '19 at 12:33
  • @SukritKapil Alternatively you can do `void shift(int x, int y, int arr[x][y]);` if you need a function accepting any 2D array. – Lundin Jun 05 '19 at 13:18
  • @Lundin Alright, would that work because int x and int y are initialised earlier than arr[x][y] and so it does not give 'uninitialised array' error? – Sukrit Kapil Jun 05 '19 at 13:30
  • @SukritKapil They are parameters to the function. The array in the example is actually a variable-length array (VLA) but it "decays" into a pointer "between the lines". – Lundin Jun 05 '19 at 14:26