Why does this cause a segmentation error?

#include<stdio.h> void foo(int **arr) { arr[1][1]++; } main() { int arr[20][20]; printf("%d\n",arr[1][1]); foo((int**)arr); printf("%d\n",arr[1][1]); } 
+7
c arrays segmentation-fault
source share
6 answers

Suppose you declare: int arr [10] [20];
What type of arr?
You might think that this is int ** , but this is not true.

Actually type int (*)[20] when it decays (for example, when you pass it to a function),
Array attenuation is applied only once.

More here


Now consider the following:

 #include<stdio.h> #include<stdlib.h> void foo(int arr[][20]) { arr[1][1]++; } main() { int (*arr)[20]; arr = malloc(sizeof(int (*)[]) * 2); //2 rows & malloc will do implicit cast. printf("%d\n",arr[1][1]); foo(arr); printf("%d\n",arr[1][1]); } 

Exit:

$ gcc fdsf.c && &. / a.out
0
one


arr and arr + 1 point to an array of 20 integers.

arr + 0 -> int int (20 ints adjacent)
[0] [0] [0] [1]
arr + 1 →; int (20 ints adjacent)
[1] [0] [1] [1]

+10
source share

Here is what int[2][2] looks like in memory:

int[2] int[2]

That is, the array immediately follows another array.

Here is what int[2] looks like in memory:

int int

That is, int immediately follows another int.

So, here it looks int[2][2] in memory:

 int int int int ^ ^ | |___ this is arr[1][1] | |____ this is p[1], assuming sizeof(int*) == sizeof(int) 

If you press arr on int** , I'm going to name the result p . Then he points to the same memory. When you do p[1][1] , you do not get arr[1][1] . Instead, the program executes, it reads the value in p[1] , sets this value to int size and plays it. If this second int contains, say, the value "21", then you simply tried to dereference the pointer "25" (if int is 4 bytes). It is not right.

Arrays do not match with pointers, and 2-D arrays are, of course, not the same as pointers to pointers.

+7
source share

Since foo expects a pointer to a pointer to an int, and you pass it a pointer to an array of 20 int. Casting will not change the fact that this is not the right type.

+6
source share

If you change it like this, you will get the expected result:

 #include<stdio.h> void foo(int arr[][20]) { arr[1][1]++; } int main() { int arr[20][20]; arr[1][1] = 1; printf("%d\n",arr[1][1]); foo(arr); printf("%d\n",arr[1][1]); } 
+5
source share

foo must know the size of the array (well, at least the second dimension of the array, not necessary at first), otherwise it cannot perform the necessary pointer arithmetic for [1][1] .

+4
source share

The problem is that int arr[20][20] for a 2d array means that this array is stored as a 1d array, and the rows are stored one by one. when indexing to int **arr you actually take the 2nd element from the first line of the array, then you cast it and take the first element there.

+1
source share

All Articles