Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[c][sizeof] - Sprawdzenie rozmiaru tablicy w zewnętrznym pliku

superduo 12 Paź 2014 15:06 876 8
  • #1 12 Paź 2014 15:06
    superduo
    Poziom 13  

    Witam,

    Chciałbym za pomocą operatora sizeof sprawdzić rozmiar tablicy zdefiniowanej w zewnętrznym pliku:

    plik main.c

    Kod: c
    Zaloguj się, aby zobaczyć kod

    plik zew.h

    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik zew.c

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Niestety kompilator wyrzuca błąd:
    Code:
    error: invalid application of 'sizeof' to incomplete type 'uint16_t[]'


    Czy jest jakiś sposób żeby sprawdzić rozmiar tablicy w pliku głównym?
    Moderowany przez piotrva:

    składnię znacznika syntax poprawiam

    0 8
  • Pomocny post
    #2 12 Paź 2014 15:10
    anonymousexd
    Poziom 24  

    Nie jest to możliwe.
    Możesz jedynie poznać rozmiar pliku albo po prostu przed tablicą zapisać jej rozmiar (jako dodatkowy int).

    Kod: c
    Zaloguj się, aby zobaczyć kod



    EDIT: chyba że chodzi ci o plik z kodem .c, w takim razie w main.c:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    A w innym pliku:


    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #3 12 Paź 2014 15:23
    superduo
    Poziom 13  

    Właśnie tak w tej chwili robie ale to mało wygodne. Dziękuje za odpowiedź :)

    0
  • #4 13 Paź 2014 17:34
    Bielak_solid
    Poziom 13  

    Z doświadczenia polecam definiowanie funkcji do pobierania wskaźnika tablicy i/lub jej rozmiaru zamiast używanie zmiennych globalnych:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    wówczas deklaracja int table[] = { ... } może być statyczna co zabezpieczy przed bezpośrednim dostępem z zewnątrz.

    Z takiej konstrukcji wynika wiele zalet:
    - ukrycie pobierania tablicy wewnątrz funkcji eliminuje zależność całego kodu od zmiennych globalnych, zmiana nazwy zmiennej lub logiki kodu nie ciągnie za sobą potrzeby poprawiania każdego miejsca gdzie używana jest tablica
    - nadzór nad dostępem do zmiennych - prosta ochrona dostępu, możliwość debugowania dostępu do tablicy.

    0
  • #5 13 Paź 2014 20:35
    BlueDraco
    Specjalista - Mikrokontrolery

    ... i parę wad - wydajność, rozmiar kodu... A co tam, klient zapłaci za większą pamięć i szybszy procesor... ;)

    0
  • #6 13 Paź 2014 20:58
    Bielak_solid
    Poziom 13  

    BlueDraco napisał:
    ... i parę wad - wydajność, rozmiar kodu... A co tam, klient zapłaci za większą pamięć i szybszy procesor... ;)


    Nie zgodzę się absolutnie. Jedno wywołanie aby pobrać wskaźnik na tablicę nie zwiększy kodu w stopniu wymagającym zmiany procesora. Tablicę można przecież pobrać do lokalnego wskaźnika i po problemie, jeśli API definiuje nam, że wskaźnik nie zmieni się w całym cyklu pracy wystarczy jedno wywołanie do kolejnego startu programu. Jedyny koszt to wywołanie funkcji.

    Pozostawienie takiej "kozy" w postaci zmiennej globalnej zwiększa koszty przy przenoszeniu oprogramowania na inny MCU/SoC. Takie skróty myślowe zawsze prowadzą do zwiększenia kosztów utrzymania oprogramowania.

    Jeśli dalej upierasz się, że rozwiązanie takie jest nieefektywne, równie dobrze można dołożyć ifdef i zamiast funkcji zdefiniować makro:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wówczas masz wybór czy chcesz funkcję czy makro. Pozostawia to pewną "furtkę" na przyszłość bez potrzeby modyfikacji kodu firmware'u. Skraca to również proces testowania oprogramowania - zmieniasz tylko jedną funkcję, nie wiele miejsc w kodzie, zatem wystarczy wytestować moduł z wprowadzoną zmianą.

    Równie dobrze można zadeklarować funkcję jako _inline_ uzyskamy pewną optymalizację (dodatkowo należy ustawić odpowiedni stopień optymalizacji dla gcc).

    Reasumując, podejście w stylu "dzisiaj działa więc zostawiam kozę oszczędzając 8B flasha" uważam za niedopuszczalne, a podsuwanie innym takich porad jako uczenie złych praktyk.

    0
  • #7 13 Paź 2014 21:47
    BlueDraco
    Specjalista - Mikrokontrolery

    To może od razu zdefiniować sprytną funkcję:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    która zgrabnie, przenośnie i niskokosztowo zastąpi brzydkie konstrukcje typu a = 2 i b = 4 eleganckimi wywołaniami laduj_2_4(&a, NULL) i laduj_2_4(NULL, &b).

    Jako inline tego Twojego paskudztwa nie zadeklarujesz, bo musiałbyś udostępnić stałe w module docelowym, czego tak bardzo chcesz uniknąć, więc realnie dokładasz ze 30 bajtów kodu funkcji i po kilkanaście bajtów na każde wywołanie zamiast max. 6 bajtów na ładowanie stałej w Cortex M.

    0
  • #8 13 Paź 2014 21:57
    Bielak_solid
    Poziom 13  

    BlueDraco napisał:
    To może od razu zdefiniować sprytną funkcję:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    która zgrabnie, przenośnie i niskokosztowo zastąpi brzydkie konstrukcje typu a = 2 i b = 4.

    Jako inline tego Twojego paskudztwa nie zadeklarujesz, bo musiałbyś udostępnić stałe w module docelowym, czego tak bardzo chcesz uniknąć.


    Przytoczony przykład zupełnie nie na miejscu. Jeśli masz lepszy pomysł proszę podaj go tutaj i wyjaśnij dlaczego jest lepszy (przykłady) zamiast krytykować innych bez podania konkretnych powodów, od tak bo ja wiem lepiej...

    Zaproponowałem swój pomysł popierając przykładami dlaczego jest to lepsze podejście.

    Temat uważam za wyczerpany. Mam nadzieję, że autor wątku znajdzie dla siebie dobre rozwiązanie :).

    Pozdrawiam

    0
  • #9 13 Paź 2014 23:08
    vonar
    Poziom 28  

    Bielak_solid napisał:
    ukrycie pobierania tablicy wewnątrz funkcji eliminuje zależność całego kodu od zmiennych globalnych, zmiana nazwy zmiennej lub logiki kodu nie ciągnie za sobą potrzeby poprawiania każdego miejsca gdzie używana jest tablica
    Tak, za to teraz zmiana nazwy funkcji dostępowej wymaga przeróbek reszty kodu.
    Zastępujesz dwa symbole globalne jednym, ale ze zwykłego wskaźnika i liczby całkowitej robi się funkcja zwracająca dwie wartości przez wskaźniki – nie jest to prostsze. A żeby przez optymalizację pozbyć się narzutu na wywołanie potrzeba LTO. Zamienił stryjek siekierkę na kijek...

    Co do lepszego rozwiązania... hmm, wiem, że to oszukiwanie ( ;) ), ale jest jeszcze C++ i std::array.
    W C można radzić sobie podobnie jak w pierwszym poście, ale w pliku nagłówkowym deklarując tablicę razem z rozmiarem:
    tablica.h
    Kod: c
    Zaloguj się, aby zobaczyć kod
    tablica.c
    Kod: c
    Zaloguj się, aby zobaczyć kod
    main.c
    Kod: c
    Zaloguj się, aby zobaczyć kod
    Co prawda rozmiar zawarty jest w pliku nagłówkowym i jego zmiana pociągnie za sobą rekompilację wszystkich dołączających go plików, ale przy aplikacji na mikrokontrolery raczej nie jest to wielki problem.

    0
TME logo Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
TME Logo