2013-07-04 14 views
5

jaki byłby wpływ na dostęp z tablicy lub w alokacji pamięci dla tych dwóch przypadków:różnica b/w przydzielania pamięci dla tablicy 2D w 1 podróży lub wiersz po wierszu

1.

int **arr; 
    arr = malloc(sizeof(int) * row * column); 

2.

int **arr; 
    arr = malloc(sizeof(*arr) * row); 
    for(i=0; i<row; i++) 
     arr[i] = malloc(sizeof(**arr) * column)); 
+2

Myślę, że masz na myśli 'malloc (wiersz * kolumna * sizeof (int));' – Kninnug

+0

tak .. dzięki za wspomnienie – user1660982

Odpowiedz

6
  • Po pierwsze, "wpływ" jest to, że pierwsza metoda jest zepsuty. Nie zadziała za pomocą wskaźnika int **.

    W celu przyporządkowania tablicę 2D w jednym ujęciu, jak próbują to zrobić w pierwszej metodzie, trzeba rzeczywiście przeznaczyć 1D tablicę dostatecznej wielkości

    int *arr = malloc(row * column * sizeof *arr); 
    // Note: `int *`, not `int **` 
    

    i wykonać dostęp przez indeks ręcznym ponowne obliczenie, np zamiast wykonywać arr[i][j] musisz zrobić arr[i * column + j].

    Próba przechowania przydzielonego wskaźnika w int **arr, a następnie uzyskanie dostępu do tablicy jako arr[i][j] spowoduje po prostu awarie.

  • Po drugie, twoja druga metoda jest OK. Po prostu w drugiej metodzie nie jest konieczne przydzielanie pamięci drugiego poziomu przez wiele niezależnych wywołań malloc. Można przeznaczyć cała pamięć drugiego poziomu jednego strzału

    int **arr = malloc(row * sizeof *arr); 
    int *arr_data = malloc(row * column * sizeof *arr_data); 
    

    a potem po prostu rozprowadzać że wstępnie przydzieloną pamięć drugiego poziomu między rzędami

    for (i = 0; i < row; i++) 
        arr[i] = arr_data + i * column; 
    

    (oczywiście, można przeznaczyć wiersze niezależnie od siebie, jeśli chcesz tak. to będzie również działać. dlatego chciałem przeznaczyć je w jednym ujęciu jest lepiej zilustrować podobieństwo między pierwszym i drugim podejściu, jak skomentował poniżej.)

Teraz, patrząc na te dwie metody, można łatwo zauważyć, że oba z nich zasadniczo robią to samo. Jedyną różnicą jest to, że w pierwszej metodzie znajdujesz początek wiersza w locie, obliczając za każdym razem arr + i * column (zauważ, że arr[i * column + j] jest równoważne). W drugiej metodzie wstępnie oblicza się wszystkie początki wierszy za pomocą tej samej formuły arr_data + i * column i przechowuje je do dalszego wykorzystania w osobnej tablicy "indeksu wiersza" arr.

Zasadniczo sprowadza się do kompromisu między wykorzystaniem pamięci (pierwsza metoda wymaga mniej pamięci) a szybkością (druga metoda jest potencjalnie, ale niekoniecznie, szybsza). W tym samym czasie druga metoda obsługuje składnię "naturalną" dla dostępu do tablicy 2D - arr[i][j], podczas gdy w pierwszej metodzie musisz użyć bardziej skomplikowanej składni dostępu 1D z ponownym obliczaniem indeksu.

+0

Dzięki @Andrey bardzo ładnie wyjaśnione. Rozumiałem wszystko. Nie będę teraz zadawał takich głupich pytań :) – user1660982

+0

+ Nie wiedziałem o tej technice przydzielania pamięci dla 2D, Dzięki! –

Powiązane problemy