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

Inicjalizacja tablicy char code a[4][3][2] w C dla AT89S52 – błąd kompilacji MIDE

zdzisio1980 06 Wrz 2007 15:43 1532 10
REKLAMA
  • #1 4256380
    zdzisio1980
    Poziom 10  
    Posty: 37
    Witam wszystkich. Mam mały problem. Pisze program w języku C na AT89S52. W programie mam taką linijkę:

    char code a[4][3][2] = {"A","B","C","D","E","F","G","H","I","J","K","L"};

    O ile w środowisku RIDE kompiluje się to bezproblemowo i program działa prawidłowo, to w MIDE (muszę go użyć gdyż kod całego przyszłego programu przekroczy na pewno magiczne 4kB - ograniczenie RIDE) pojawia się taki error:
    error 69: struct/union/array 'a' : initialization needs curly braces

    Dorzuciłem więc jeszcze raz nawias klamrowy (choć nie wiem po co):

    char code a[4][3][2] = {{"A","B","C","D","E","F","G","H","I","J","K","L"}};

    Plik się skompilował, z ostrzeżeniem :
    warning 147: excess elements in array initializer after a

    Program nie działa jednak prawidłowo, więc dorzuciłem
    jeszcze jeden nawias klamrowy:

    char code a[4][3][2] = {{{"A","B","C","D","E","F","G","H","I","J","K","L"}}};

    Plik skompilował się bez ostrzeżeń, ale program nie działa prawidłowo.

    Za wszelkie wskazówki gdzie jest błąd będę wdzięczny.
  • REKLAMA
  • #2 4256537
    Mad Bekon
    Poziom 23  
    Posty: 794
    Pomógł: 31
    Ocena: 36
    A niby jak ma wyglądać ta twoja tablica?
    Bo mi się coś widzi, że to powinno byc tak:
    char code a[4][3][2]={
    {{'A','B'},{'C','D'},{'E','F'}},
    {{'G','H'},{'I','J'},{'K','L'}},
    {{'M','N'},{'O','P'},{'R','S'}},
    {{'T','U'},{'W','X'},{'Y','Z'}}
    }

    Nie bardzo kumam czemu tą tablice organizujesz tak a nie inaczej
  • #3 4256641
    aster11
    Poziom 19  
    Posty: 211
    Pomógł: 36
    Ocena: 1
    Musisz odwzorować poprzez nawiasy klamrowe zagnieżdżoną, wielowymiarową postać zadeklarowanej tablicy, czyli powinno być tak:
    char code a[4][3][2] = {{"A","B","C"},{"D","E","F"},{"G","H","I"},{"J","K","L"}};

    Standard języka C zakłada, że bez takiego wyróżnienia, wartości inicjalizujące będą zapisywane kolejno, tak jakby była to tablica jednowymiarowa, zaczynająca się pod takim samym adresem, gdzie dana tablica wielowymiarowa. Niestety SDCC nie chce tego akceptować. Może to i bezpieczniej dla programisty. Jeżeli chcesz mieć tablice 4 x 3 łańcuchy dwuznakowe, to zainicjuj ją tak, jak sobie zadeklarowałeś :!::D
  • REKLAMA
  • #4 4256678
    Mad Bekon
    Poziom 23  
    Posty: 794
    Pomógł: 31
    Ocena: 36
    Bezsensowne jest deklarowanie tych dwuznakowych, skoro i tak pchasz tam po jednym znaku.
    Lepiej tak:

    char code a[4][3] = {{'A','B','C'},{'D','E','F'},{'G','H','I'},{'J','K','L'}};

    Oszczędzasz połowę pamięci!
  • #5 4256749
    aster11
    Poziom 19  
    Posty: 211
    Pomógł: 36
    Ocena: 1
    Cytat:
    Bezsensowne jest deklarowanie tych dwuznakowych, skoro i tak pchasz tam po jednym znaku.

    Nie takie bezsensowne!!! Bardzo istotną i podstawową sprawą jest wiedzieć czym różni się w języku C "A" od 'A'. Większość funkcji bibliotecznych, operujących na ciągach znaków, potrzebuje tej pierwszej postaci. Lepiej zapewne od razu zdefiniować je jak trzeba, niż potem kombinować.
  • REKLAMA
  • #7 4256980
    aster11
    Poziom 19  
    Posty: 211
    Pomógł: 36
    Ocena: 1
    Cytat:
    Jakoś nigdy nie miałem takiej potrzeby
    .

    Hmm, czy rozumiesz jak wygląda w języku C definiowanie łańcuchów znaków i na czym polega ich "reprezentacja" za pomocą typu char*.
    Sam w jednym ze swoich postów piszesz tak ...

    Cytat:
    ja mam tak, zawsze działało bez problemów:

    int USART_Transmit( unsigned char data )
    {
    while ( !( UCSRA & (1<<UDRE)) );
    UDR = data;
    return 0;
    }

    void USART_PutS (char *text)
    {
    while (*text)
    USART_Transmit(*text++);
    }


    ... i też dla oszczędności, jeśli chciałeś wypisać A, to wysyłałeś do USART_PutS 'A', zamiast "A", i wszystko działo dobrze ???

    Cytat:
    Mógłbyś podać przykład takiej funkcji?


    Jeden przykład sam sobie dałeś, jest powyżej. Po inne zaglądnij np. do pliku nagłówkowego string.h.
  • REKLAMA
  • #8 4257223
    Mad Bekon
    Poziom 23  
    Posty: 794
    Pomógł: 31
    Ocena: 36
    Pisząc, że nie widziałem potrzeby, miałem na myśli, żeby robić 2 komórki dla przechowywania jednej litery.
    Jakoś nadal nie widzę sensu stosowania Ciągu w przypadku jednej litery.

    Jeśli chcę wysłać A to robię USART_Transmit('A');

    USART_PutS("A") mija się z celem, zajmuje więcej taktów zegarowych.

    Tak samo jak nie widzę sensu w tworzeniu tablicy 2 elementowej, żęby przechowywać jeden znak.

    I akurat mnie nie musisz tłumaczyć róznicy między " " a ' '.
    Chciałem tylko, żeby autor tematu zrozumiał, że tworzona przez niego tablica w przypadku przechowywania jednej litery jest marnotrawieniem pamięci, której i tak nie jest zbyt wiele.

    Jeśli robiłem to faktycznie przez PutS, to pewnie robiłem to na szybko nie optymalizując jeszcze kodu.
  • #9 4258097
    zdzisio1980
    Poziom 10  
    Posty: 37
    Dzięki aster11. Zadeklarowałem tak jak napisałeś i działa.

    Odpowiedź dla kolegi Mad Bekon: ja nie chcę przechowywać samego znak tylko c-string czyli znak + 0, bo tak mi później wygodniej.

    Jeszcze małe pytanko (dla upewnienie się):
    jeżeli utworzę tablice np. char tab[3][2][2] = {0,1,2,3,4,5,6,7,8,9,10,11};
    to elementy w tablicy są tak rozmieszczone:

    tab[0][0][0] = 0;
    tab[0][0][1] = 1;
    tab[0][1][0] = 2;
    tab[0][1][1] = 3;
    tab[1][0][0] = 4;
    tab[1][0][1] = 5;
    tab[1][1][0] = 6;
    tab[1][1][1] = 7;
    tab[2][0][0] = 8;
    tab[2][0][1] = 9;
    tab[2][1][0] = 10;
    tab[2][1][1] = 11;

    Czy SDCC się temu sprzeciwi?
  • #10 4258242
    aster11
    Poziom 19  
    Posty: 211
    Pomógł: 36
    Ocena: 1
    Tak, elementy właśnie tak powinny zostać ułożone, zgodnie ze standardem języka C.
    SDCC najprawdopodobniej się sprzeciwi (nie chce mi się sprawdzać :) ), podobnie jak w Twoim poprzednim przykładzie. Trzeba będzie po prostu jawnie powstawiać nawiasy, określające każdy poziom zagnieżdżenia - po dwie liczby w nawiasie (tablica najbardziej "zewnętrzna"), potem po dwa takie nawiasy w następnych nawiasach (tab. środkowa) i w końcu trzy zbiory 2x2, każdy w swoim nawiasie, umieszczone w klamrze głównej.

    Zasada ta jest intuicyjna - szczegóły powinny być wytłumaczone w każdym bardziej skrupulatnym opracowaniu, omawiającym język C.
  • #11 4258948
    zdzisio1980
    Poziom 10  
    Posty: 37
    Ok. Dzięki za pomoc.

Podsumowanie tematu

✨ Problem dotyczy inicjalizacji trójwymiarowej tablicy znaków typu char code a[4][3][2] w języku C dla mikrokontrolera AT89S52 przy użyciu kompilatora SDCC w środowisku MIDE. Próby inicjalizacji tablicy za pomocą płaskiej listy łańcuchów znaków ("A", "B", ...) bez odpowiedniego zagnieżdżenia nawiasów klamrowych skutkują błędami kompilacji lub ostrzeżeniami o nadmiarowych elementach. Kompilator SDCC wymaga dokładnego odwzorowania struktury tablicy poprzez zagnieżdżone nawiasy klamrowe odpowiadające wymiarom tablicy, np. char code a[4][3][2] = {{{'A','B'},{'C','D'},{'E','F'}}, ...}. Dyskusja podkreśla różnicę między pojedynczym znakiem ('A') a łańcuchem znaków ("A") w C oraz konsekwencje pamięciowe i funkcjonalne tych typów. Zasugerowano, że dla pojedynczych znaków lepiej używać tablic dwuwymiarowych char a[4][3], co oszczędza pamięć. Autor potwierdził, że deklaracja z odpowiednimi nawiasami działa poprawnie. Ponadto omówiono sposób rozmieszczenia elementów w tablicy wielowymiarowej zgodnie ze standardem C oraz konieczność jawnego zagnieżdżania inicjalizatorów w SDCC.
Wygenerowane przez model językowy.
REKLAMA