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

[Atmega][avr-gcc] - Wskaźnik do struktury w strukturze

gadula88 20 Sty 2014 22:43 2304 10
  • #1 13201152
    gadula88
    Poziom 15  
    Witam!
    Przerabiam trochę menu kolegi tmf z pierwszej książki i napotkałem na problem. Chciałem oryginalną strukturę opisującą menu:

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

    przerobić dodając opcję wyboru języka komunikatów:

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


    Teraz przy próbie odczytu tekstu ze struktury:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    dostaję błąd:

    Cytat:
    Error 11 'struct _menuitem' has no member named 'text_ang'
    Error 10 'struct _menuitem' has no member named 'text_pl'
    Error 4 2238 : no member named 'text_ang' in '_menuitem'
    Error 2 2238 : no member named 'text_pl' in '_menuitem'
    Warning 1 3545 : cast to 'void *' from smaller integer type 'uint16_t' (aka 'unsigned short')
    Warning 3 3545 : cast to 'void *' from smaller integer type 'uint16_t' (aka 'unsigned short')
    Warning 5 3545 : cast to 'void *' from smaller integer type 'uint16_t' (aka 'unsigned short')
    Warning 6 3545 : cast to 'void *' from smaller integer type 'uint16_t' (aka 'unsigned short')
    Warning 7 3545 : cast to 'void *' from smaller integer type 'uint16_t' (aka 'unsigned short')
    Warning 8 3545 : cast to 'void *' from smaller integer type 'uint16_t' (aka 'unsigned short')
    Warning 9 3545 : cast to 'void *' from smaller integer type 'uint16_t' (aka 'unsigned short')


    Czy ktoś mógłby mi wskazać/naprowadzić gdzie popełniam błąd, bo zdawało mi się że mam pojęcie o wskaźnikach, ale czym dłużej szukam i czytam tym większy mam mętlik w głowie.
  • #2 13201841
    BlueDraco
    Specjalista - Mikrokontrolery
    A czego konkretnie nie rozumiesz w tym komunikacie kompilatora:
    "Error 11 'struct _menuitem' has no member named 'text_ang' "
  • #3 13201966
    gadula88
    Poziom 15  
    Nie rozumiem, dlaczego przy próbie pobrania adresu do text_ang ze struktury lang, szuka go w strukturze tmpmenuitem (_menuitem), gdzie oczywiście go nie ma. Sądziłem że w ten sposób:
    Cytat:
    const struct _lang *lang = tmpmenuitem->text;

    pobiorę wskaźnik na odpowiednią strukturę, w której będą potrzebne napisy.
  • #4 13202172
    BlueDraco
    Specjalista - Mikrokontrolery
    Zacznij od przyjrzenia się linii programu, której dotyczy komunikat o błędzie.
  • #5 13202735
    Eagle
    Poziom 24  
    Cytat:

    Nie rozumiem, dlaczego przy próbie pobrania adresu do text_ang ze struktury lang, szuka go w strukturze tmpmenuitem (_menuitem), gdzie oczywiście go nie ma.


    Ponieważ wskazujesz wskaźnikiem do struktury _menuitem wiec kompilator posłusznie tam szuka pola o nazwie text_ang, nie znajduje i rzuca błędem.
    Być może chodzi ci o coś takiego
    Kod: text
    Zaloguj się, aby zobaczyć kod


    P.S. W przyszłości zamieszczaj ten fragment kodu który generuje błąd.
  • Pomocny post
    #6 13204449
    Andrzej__S
    Poziom 28  
    Należy pamiętać, że w nowszych wersjach avr-libc nie należy używać PROGMEM do deklaracji typu:
    <avr/pgmspace.h> napisał:

    Typedef Documentation
    prog_char

    Note:
    DEPRECATED

    This typedef is now deprecated because the usage of the __progmem__ attribute on a type is not supported in GCC. However, the use of the __progmem__ attribute on a variable declaration is supported, and this is now the recommended usage.



    czyli powinno być raczej jakoś tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Druga sprawa, jeśli przykładowa struktura menuitem1 zapisana jest w pamięci programu, to nie odczytasz jej w ten sposób:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Zamiast tego należy użyć:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #7 13204515
    tmf
    VIP Zasłużony dla elektroda
    Nie do końca. To co zaproponowałeś to wyrzucenie PROGMEM, co spowoduje, że wskaźnik nie będzie we FLASH, ma być:
    const PROGMEM char *text;
    Nie powinno się PROGMEM używać z typedef.
    Jeśli wskaźnik już będzie w FLASH to można pole odczytać tak jak podałeś, lub użyć tego co pokazałem w przykładzie, czyli własnej funkcji GetAddr - robi ona dokładnie to samo, lecz ukrywa zbedne szczegóły i kod staje się bardziej przejrzysty.
  • #8 13204608
    gadula88
    Poziom 15  
    Czyli w tych moich zmienionych strukturach:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Aby móc odwołać się do "text", muszę wykonać coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Czy dobrze myślę?
    Jak później wyciągnąć adresy do poszczególnych napisów, by móc je wyświetlić na wyświetlaczu?
  • #9 13204971
    tmf
    VIP Zasłużony dla elektroda
    Dobrze myślisz, pola z tej struktury odczytujesz albo poprzez zmodyfikowaną funkcję GetAddr, albo przez pgm_read jak pokazał kolega Andrzej.
    Z drugiej strony, dlaczego nie skorzystasz z anonimowej struktury i nie osadzisz pól text bezpośrednio w _menuitem? Uprości to kod i zaoszczędzi jednego wskaźnika.
  • #10 13205672
    Andrzej__S
    Poziom 28  
    tmf napisał:
    Nie do końca. To co zaproponowałeś to wyrzucenie PROGMEM, co spowoduje, że wskaźnik nie będzie we FLASH, ma być:
    const PROGMEM char *text;


    Nie bardzo rozumiem. Czy jeśli użyję PROGMEM przy deklarowaniu stałej (tak jak to zrobiłem):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    to cała struktura menuitem1 włącznie ze wskaźnikiem na text1 nie znajdzie się w pamięci programu?

    A sam wskaźnik jest chyba prawidłowo:
    <avr/pgmspace.h> napisał:

    #define PGM_P const char *

    //Used to declare a variable that is a pointer to a string in program space.
  • #11 13212260
    gadula88
    Poziom 15  
    Wielkie dzięki za pomoc! Kod się już kompiluje i działa, a ja uzupełniłem swoją wiedzę :)
    tmf napisał:

    Z drugiej strony, dlaczego nie skorzystasz z anonimowej struktury i nie osadzisz pól text bezpośrednio w _menuitem? Uprości to kod i zaoszczędzi jednego wskaźnika.

    Też o tym myślałem, ale potraktowałem problem jako pracę domową/wyzwanie :)
REKLAMA