簡體   English   中英

為什么會產生分段錯誤?

[英]Why does this generate a 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]);
}

假設您聲明: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 int ... int(20個整數,連續)
[0] [0] [0] [1]
arr + 1-> int int int ... int(20個整數,連續)
[1] [0] [1] [1]

這是一個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個字節)。 那是不對的。

數組與指針不一樣,二維數組與指針到指針當然也不一樣。

因為foo期望有一個指向int的指針,並且您正在向它傳遞一個指向20個int數組的指針。 強制轉換它不會改變它不是正確類型的事實。

如果您這樣更改它,您將獲得預期的結果:

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

foo需要知道數組的大小(嗯,至少不需要第二個數組的維,第一個是不需要的),否則它不能為[1][1]做必要的指針運算。

問題是2d數組的int arr[20][20]意味着此數組存儲為1d數組,並且一行接一行地存儲行。 當您索引到int **arr ,實際上是從數組的第一行獲取第二個元素,然后取消引用它,然后從那里獲取第一個元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM