logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Tablica dwuwymiarowa w gcc

Krzych12 18 Paź 2011 13:10 2494 14
  • #1 10039569
    Krzych12
    Poziom 12  
    Witam

    Na początku chciałbym napisać że piszę program w AVR Studio, korzystając z kompilatora gcc. Mam kilka pytań:

    W jaki sposób zadeklarować wskaźnik do tablicy dwuwymiarowej, której postać przedstawiona jest poniżej:

    volatile unsigned char lcd_text[][16] = {"kanal 1-nap.: ", "kanal 1-hist.: ", "kanal 1-on/off:" } ;


    Druga sprawa jak później odwołać się do elementu np: "kanal 1-hist.:"
  • #3 10039606
    Krzych12
    Poziom 12  
    Po zadeklarowaniu wskaźnika

    Cytat:
    volatile unsigned char (*wskaznik)[][];


    Kompilator zgłasza jak poniżej:

    Cytat:
    ../: error: array type has incomplete element type
  • #5 10041172
    nsvinc
    Poziom 35  
    Ewentualnie olać takie indeksowanie i używać po prostu wskaźników.

    Jeśli zrobisz tablicę wyglądającą tak:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    to sam lcd_text jest wskaźnikiem na wskaźnik. Czyli identyfikuje po prostu tablicę wskaźników.
    Jeśli chcesz mieć wskaźnik na tą tablicę, to musisz zadeklarować wskaźnik na wskaźnik na wskaźnik:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    do którego możesz przypisać wskaźnik na tablicę lcd_text
    Kod: text
    Zaloguj się, aby zobaczyć kod

    i odwoływać się do konkretnego napisu w sposób (*wsk_lcd_text)[n] w wyniku czego otrzymasz wskaźnik na pierwszy znak napisu o indeksie n.

    Dla przykładu,
    (*wsk_na_lcd_text)[0][1] to już nie wskaźnik, a unsigned char, w którym siedzi (w ASCII) literka 'a' - z stringa napis.
    (*wsk_na_lcd_text)[1][5] będzie unsigned charem z znakiem '2', z stringa napis2

    Można też bez '*', czyli wsk_na_lcd_text[0][0][1] jest ekwiwalentny do (*wsk_na_lcd_text)[0][1].
  • #6 10041422
    Freddie Chopin
    Specjalista - Mikrokontrolery
    nsvinc napisał:
    volatile unsigned char *volatile**wsk_lcd_text; //wskaźnik na volatile wskaźnik na wskaźnik

    To volatile po drodze jest IMHO zbędne, bo niby czemu ten wskazywany wskaźnik jest volatile?

    4\/3!!
  • #8 10046258
    Krzych12
    Poziom 12  
    Po kompilacji kodu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kompilator ostrzega o bledzie:
    Cytat:
    ../Wskaznik.c:8: warning: assignment from incompatible pointer type


    I po wykonaniu build'owania w kodzie po zdeasemblowaniu nie widać prawidłowego adresu do stringu lcd_text

    Kompilator gcc za bardzo nie odpowiada kompilatorowi w C, ma jakieś inne podejście do kodu.
  • #9 10046290
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Dwuwymiarowa tablica nie-dynamiczna wcale nie składa się z jednowymiarowej tablicy wskaźników na jednowymiarowe tablice, więc czemu się dziwisz że nie działa? Szukaj dalej błędu w kompilatorze, a nie u siebie...

    Pytałeś na początku jak zadeklarować taki wskaźnik, dostałeś odpowiedź - sprawdziłeś ją, czy od razu przeszedłeś do potrójnych wskaźników?

    4\/3!!
  • #10 10046417
    nsvinc
    Poziom 35  
    Sh!t, ale wtopa...

    Więc spiesze z prawidłowym wyjaśnieniem:

    Sam lcd_text jest pojedyńczym wskaźnikiem na pamięć, tj. pierwszy bajt pierwszego elementu. Czyli jego najprostsza dereferencja *lcd_text wskazuje na literkę 'n' tekstu napis1.

    Taka tablica w pamięci wygląda następująco (adresy kolejnych bajtów rosną w prawo):
    napis1[null][9x padding]napis2[null][9x padding]napis3[null][9x padding]
    Tablica dwuwymiarowa w gcc

    Dziewięć bajtów padding-u wynika z faktu, że zadeklarowałeś jeden z wymiarów tablicy w liczbie 16. Czyli na każdy tekst masz 16 znaków, a znaki 'niewykorzystane' będą właśnie paddingiem, i te bajty mogą być zerami lub losowe.


    Aby uzyskać wskaźnik na lcd_text, można zadeklarować zwykły podwójny wskaźnik
    Kod: text
    Zaloguj się, aby zobaczyć kod

    i kazać mu wskazywać na lcd_text
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Dostęp do znaków:
    *(*wsk) będzie unsigned charem z literką 'n' z napis1
    (*wsk)[16] będzie unsigned charem z literką 'n' z napis2
    (*wsk)[18] będzie unsigned charem z literką 'p' z napis2

    Konkludując, wystarczy podwójny wskaźnik...
  • #12 10048957
    gaskoin
    Poziom 38  
    nsvinc napisał:

    Kod: text
    Zaloguj się, aby zobaczyć kod

    i kazać mu wskazywać na lcd_text
    Kod: text
    Zaloguj się, aby zobaczyć kod



    a nie przypadkiem wsk = lcd_text ? Sam napisałeś że lcd_text jest już wskaźnikiem więc to co napisałeś przepisze do wskaźnika nie to co trzeba :P
  • #13 10049670
    nsvinc
    Poziom 35  
    Chcemy wskazywać na ten wskaźnik, a nie otrzymać jego kopię.

    Kod: text
    Zaloguj się, aby zobaczyć kod

    wypluje warning/błąd o niekompatybilności typów, ponieważ lcd_text jest wskaźnikiem pojedyńczym, a wsk podwójnym.

    Aby móc wskazywać na wskaźnik lcd_text, potrzebujemy uzyskać adres, pod którym ten wskaźnik się znajduje, więc &lcd_text jest już wskaźnikiem na wskaźnik (bo uzyskujemy adres wskaźnika), który można już bezpiecznie przypisać do zmiennej wsk...
  • Pomocny post
    #14 10051557
    PDT
    Poziom 24  
    Krzych12 zmień swój przykład na wzór poniższego:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    i będzie dobrze. Powodzenia.
  • #15 10052798
    Krzych12
    Poziom 12  
    PDT to zadziałało, wielkie dzięki.
REKLAMA