为什么会产生分段错误?

avd*_*avd 7 c arrays segmentation-fault

#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]);
}
Run Code Online (Sandbox Code Playgroud)

N 1*_*1.1 10

假设你声明:int arr [10] [20];
什么类型的arr?
你可能认为这是int **,但这是不正确的.

int (*)[20]当它衰变时它实际上是类型(比如当你将它传递给函数时);
数组衰减仅适用一次.

细节在这里


现在考虑以下,

#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]);
}
Run Code Online (Sandbox Code Playgroud)

输出:

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


arrarr + 1指向20个整数的数组.

arr + 0 - > int int int ... int(20 ints,contiguous)
             [0] [0] [0] [1]
arr + 1 - > int int int ... int(20 ints,contiguous)
             [1] [0] [1] [1]


Ste*_*sop 7

这是int[2][2]内存中的样子:

int[2] int[2]

也就是说,一个数组紧跟另一个数组.

这是int[2]内存中的样子:

int int

也就是说,一个int紧跟另一个int.

所以,这里也是int[2][2]内存中的样子:

int int int int
     ^       ^
     |       |___ this is arr[1][1]
     |
     |____ this is p[1], assuming sizeof(int*) == sizeof(int)
Run Code Online (Sandbox Code Playgroud)

如果你投arr了一个int**,我打算调用结果p.然后它指向相同的记忆.当你这样做时,p[1][1]你没有得到arr[1][1].该程序所做的是,它读取值p[1],通过int的大小调整,并取消引用它.如果第二个int包含,例如值"21",那么您刚刚尝试取消引用指针"25"(如果int是4个字节).那是不对的.

数组与指针不同,2-D数组肯定与指针指针不同.


APr*_*mer 6

因为foo期望指向int的指针,并且你正在向它传递一个指向20 int数组的指针.投射它不会改变它不是正确类型的事实.


Luc*_*cas 5

如果你这样改变它,你会得到预期的结果:

#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]);
}
Run Code Online (Sandbox Code Playgroud)