为什么这会产生分段错误?

发布于 2024-08-25 00:53:08 字数 203 浏览 6 评论 0原文

#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]);
}
#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]);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

爱,才寂寞 2024-09-01 00:53:08

假设您声明:
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]);
}

输出:

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


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

arr + 0 -->            int   ...    int (20整数,连续)
          [0][0]   [0][1]
arr + 1 -->            int   ...    int (20整数,连续)
          [1][0]   [1][1]

Suppose you declare:
int arr[ 10 ][ 20 ] ;
What type is arr?
You may think that it's int **, but that's incorrect.

Its actually of type int (*)[20] when it decays (like when you pass it to a function);
Array decaying applies only once.

Details 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]);
}

Output :

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


arr and arr+1 are pointing to array of 20 integers.

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]

赢得她心 2024-09-01 00:53:08

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)

如果将 arr 转换为 int**,我我将调用结果p。然后它指向同一个内存。当您执行 p[1][1] 时,您不会得到 arr[1][1]。相反,程序执行的操作是读取 p[1] 处的值,将其调整为 int 的大小,然后取消引用。如果第二个 int 包含值“21”,那么您刚刚尝试取消引用指针“25”(如果 int 是 4 个字节)。那是不对的。

数组与指针不同,二维数组当然也与指向指针的指针不同。

Here's what an int[2][2] looks like in memory:

int[2] int[2]

That is, an array immediately followed by another array.

Here's what an int[2] looks like in memory:

int int

That is, an int immediately followed by another int.

So, here's also what an int[2][2] looks like in memory:

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

If you cast arr to an int**, I'm going to call the result p. Then it points to the same memory. When you do p[1][1] you don't get arr[1][1]. What the program does instead is, it reads the value at p[1], adjusts that up by the size of an int, and dereferences it. If that second int contained, say, the value "21" then you have just tried to dereference the pointer "25" (if int is 4 bytes). That ain't right.

Arrays are not the same as pointers, and 2-D arrays are certainly not the same thing as pointers-to-pointers.

肥爪爪 2024-09-01 00:53:08

因为 foo 期望一个指向 int 的指针,而您正在向它传递一个指向 20 int 数组的指针。转换它不会改变它不是正确类型的事实。

Because foo expect a pointer to a pointer to int and you are passing it a pointer to an array of 20 int. Casting it won't change the fact that it isn't the correct type.

落花浅忆 2024-09-01 00:53:08

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

#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]);
}

If you change it like this, you 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]);
}
叹沉浮 2024-09-01 00:53:08

foo 需要知道数组大小(嗯,至少是第二个数组维度,第一个不需要),否则它无法为 [1][ 执行必要的指针算术1]

foo needs to know the array size (well, at least the second array dimension, first isn't needed), otherwise it can't do the necessary pointer arithmetic for the [1][1].

坐在坟头思考人生 2024-09-01 00:53:08

问题是 2d 数组的 int arr[20][20] 意味着该数组存储为 1d 数组,并且行是一个接一个地存储的。当您对 int **arr 进行索引时,您实际上从数组的第一行获取第二个元素,然后取消引用它并在那里获取第一个元素。

Problem is that int arr[20][20] for 2d array means that this array is stored as 1d array, and lines are stored one after other. when you do indexing to int **arr you actually take 2nd element from first line of array, then you dereference it and take first element there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文