X

[C]Wskaźnik do tablicy dwuwymiarowej, obsługa

14 Nov 2008 18:08 KRkrzyfn
  • #1 14 Nov 2008 18:08
    krzyfn
    Level 12  
    Helpful post? (0)
    Witam, głowię się dłuższy czas jak poruszać się jednym wskaźnikiem po tablicy dwuwymiarowej.

    Code:
    int **wsk, tab[10][10];
    wsk = (int**)tab; // wsk = tab nie przechodzi, nie wiem czemu
    
    tab[0][0] = 5;
    tab[0][1] = 7;
    tab[1][0] = 9;
    
    printf("%d, %d", *wsk, *(wsk+1));
    


    jak wyświetlić element tab[1][0] ?

    i czemu
    Quote:

    printf("%d", **wsk);

    nie przechodzi ?

    W ogóle jak poruszać się jednym wskaźnikiem po całej tablicy. Nie interesuje mnie rozwiązanie z dwoma wskaźnikami. Chcę przekazywać jeden wskaźnik do funkcji i mieć dostępną całą tablicę dwuwymiarową, a nie tylko jeden jej wiersz.

    A może trzeba zadeklarować tablicę wskaźników na wiersze tablicy dwuwymiarowej i wskaźnik do tej tablicy przekazywać do funkcji ?
  • #2 14 Nov 2008 19:17
    Dr.Vee
    VIP Zasłużony dla elektroda
    Helpful post? (+1)
    Krótka odpowiedź: tak się nie da. :)

    Długa odpowiedź: mówiąc o wskaźniku na tablicę wielowymiarową musisz podać wszystkie oprócz ostatniego wymiaru. Czyli tak naprawdę musiałbyś napisać:
    Code:
    #include <stdio.h>
    
    int main(void)
    {
    int tab[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
    int (*wsk)[3] = tab;
    
    printf("%d\n", **wsk);
    printf("%d\n", *(*(wsk)+1));
    printf("%d\n", *(*(wsk+1)));
    return 0;
    }

    Polecam program "cdecl" do odcyfrowywania i tworzenia "magicznych" typów C w stylu tablica wskaźników na funkcje z argumentem: wskaźnik na tablicę funkcji (void) -> int zwracających ... i tak dalej :)

    Przykładowo
    Code:
    kokr@copper:/tmp/c$ cdecl
    Type `help' or `?' for help
    cdecl> declare tab as array of pointer to function (pointer to function (void) returning int) returning pointer to int
    int *(*tab[])(int (*)(void ))
    cdecl> explain int *(*tab[])(int (*)(void ))
    declare tab as array of pointer to function (pointer to function (void) returning int) returning pointer to int

    Pozdrawiam,
    Dr.Vee
  • #3 14 Nov 2008 20:08
    krzyfn
    Level 12  
    Topic author Helpful post? (+1)
    Eh. To smutne. Myślałem, że w C da się wszystko :).

    Moim zadaniem jest napisać program do transpozycji macierzy z wstawką asemblerowską.

    Chciałem zrobić dynamicznie stworzoną tablice (malloc) po podaniu wymiarów macierzy. Następnie napisać funkcję drukującą macierz (działającą na trzech argumentach - wskaźnik do tablicy, x i y).

    Teraz widzę jednak, iż będę musiał zrobić dwa wskaźniki (pionowy i poziomy).

    Jeszcze jedno pytanie:

    Słyszałem o czymś takim jak 'argumenty domniemane'. Można je rzekomo definiować:

    Code:
    funkcja(int a, int b = 10);


    A teraz chcę aby moje funkcje do obsługi macierzy potrafiły działać na dwóch argumentach (dla macierzy prostokątnych), albo na jednym (dla kwadratowych).

    W skrócie można to zrobić poprzez przeładowanie funkcji (napisanie dwóch funkcji z różną ilością argumentów). Jednak ja chciałbym jeszcze krócej, dlatego stworzyłem coś takiego:

    Code:
    funkcja(int a, int b = a);


    Kompilator tego nie przyjmuje. Jak to zrobić, żeby działało ? ^^
  • #4 17 Nov 2008 12:13
    Krashan7
    Level 17  
    Helpful post? (0)
    Argumenty domniemane działają tylko w C++.

    Co do tablic wielowymiarowych, to zwykle symuluję je za pomocą tablicy jednowymiarowej i operacji na wskaźnikach. Przykładowo tablica int-ów 6 x 3:
    Code:
    int tab[6*3];
    // pobieram element [wiersz, kolumna]
    int element = tab[wiersz * 6 + kolumna];
    

    Zdaję sobie sprawę, że nie jest to zbyt elegancki zapis, ale od eleganckich zapisów jest C++, C jest od wydajności i zwartości kodu.
  • #5 17 Nov 2008 21:40
    Dr.Vee
    VIP Zasłużony dla elektroda
    Helpful post? (0)
    Transpozycja macierzy jest akurat najprostszą operacją, po prostu zamieniasz kolejność indeksów nie ruszając w ogóle danych w macierzy :)

    Nawet w c++ nie uda Ci się taka deklaracja funkcji
    Code:
    void funkcja(int a, int b = a);
    W tym przypadku a musi być wyrażeniem stałym (albo stałą globalną). Jak chcesz obsługiwać jedną funkcją różne typy macierzy, to zadeklaruj sobie odpowiedni typ dla macierzy, np:
    Code:
    typedef struct {
    size_t rozmiar1;
    size_t rozmiar2;
    int *dane;
    } macierz_t;
    
    void transponuj(macierz_t *macierz) {
    if (macierz->rozmiar1 == macierz->rozmiar2)
    /* kod dla macierzy kwadratowej */
    else
    /* kod dla macierzy prostokątnej */
    }

    Implementacja dynamicznych macierzy wielowymiarowych tak jak napisał Krashan7, albo zobacz http://c-faq.com/aryptr/dynmuldimary.html

    Pozdrawiam,
    Dr.Vee
  • #6 22 Nov 2008 14:46
    eros81
    Level 14  
    Helpful post? (+1)
    Witam
    Pewnie autorowi to już się nie przyda ale zamieszczam przykładowy kod:
    Code:
    #include <stdio.h>
    
    int main() {
    unsigned char tab[10][10];
    unsigned char x,y;
    
    printf ("\nAnaliza tablic oraz wskaźników do nich\n\n");
    
    for (x=0;x<10;x++)	//wypełnianie elementów tablicy
    	for (y=0;y<10;y++)
    		tab[x][y]=x*10+y;
    
    printf ("Tablica:\n");
    for (x=0;x<10;x++){
    	for (y=0;y<10;y++){
    		printf ("|%d",tab[x][y]);
    	}
    	printf ("|\n");		// przeskok do nowej lini co 10
    }
    
    unsigned char *wsk;
    wsk=&tab[0][0];		//przypisanie wskaźnikowi adresu pierwszego elementu z tablicy
    
    printf ("\nTablica z wskaźników:\n");
    
    for (x=0;x<10;x++){
    	for (y=0;y<10;y++)
    		printf ("|%d",*(wsk+x*10+y));		//elementy tablicy w pamieci programu ułozone są 
    						//liniowo, jeden za drugim
    	printf ("|\n");		// przeskok do nowej lini co 10
    }
    
    return (0);
    }
Mouser  Search 4 million + Products
Browse Products