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

Inicjalizacja zmiennej globalnej

Fajfer2 11 Gru 2010 16:17 2938 16
  • #1 8854854
    Fajfer2
    Poziom 20  
    Czy zmienna złożona
    
    typedef struct Modbus
    {
    
    	volatile char ErrorFrame;
    	volatile char ErrorOrder;
    	volatile char TimeOut;
    	volatile char Message;
    	volatile char SendBlank;
    	volatile char SupervisorTimer;
    	volatile char ErrorAddress;
    
    }FlagProtocol;
    
    volatile FlagProtocol FlagModbus;
    


    zostanie zainicjowana automatycznie (do wartości 0) ?
  • #3 8855441
    Fajfer2
    Poziom 20  
    kompilator AVR-Studio (AVR-GCC).
  • Pomocny post
    #4 8856617
    mirekk36
    Poziom 42  
    W AVR GCC wszystkie zmienne globalne i statyczne są automatycznie zerowane i nie ma najmniejszej potrzeby ich inicjalizacji zerami.

    Jeśli natomiast definicja zmiennej znajduje się wewnątrz funkcji to już trzeba ją samemu inicjalizować.
  • Pomocny post
    #5 8856782
    tmf
    VIP Zasłużony dla elektroda
    Dżyszla napisał:
    Zależne od kompilatora, a czasem wręcz od jego ustawień. Dobrym nawykiem jest inicjować nawet wtedy, gdy nie ma takiej potrzeby w danym środowisku.


    Nieprawda. Wszystkie zmienne globalne są domyślnie zainicjowane wartością zero, niezależnie czy są to typy proste czy złożone. Wynika to wprost ze standardu języka c.

    Dodano po 1 [minuty]:

    mirekk36 napisał:
    W AVR GCC wszystkie zmienne globalne i statyczne są automatycznie zerowane i nie ma najmniejszej potrzeby ich inicjalizacji zerami.

    Jeśli natomiast definicja zmiennej znajduje się wewnątrz funkcji to już trzeba ją samemu inicjalizować.


    Co jest dosyć oczywiste, bo nie jest wtedy zmienną globalną :) Przy czym istnieje wyjątek - lokalne zmienne statyczne również inicjowane są na 0.
  • Pomocny post
    #6 8857065
    mirekk36
    Poziom 42  
    tmf napisał:

    mirekk36 napisał:
    W AVR GCC wszystkie zmienne globalne i statyczne są automatycznie zerowane i nie ma najmniejszej potrzeby ich inicjalizacji zerami.

    Jeśli natomiast definicja zmiennej znajduje się wewnątrz funkcji to już trzeba ją samemu inicjalizować.


    Co jest dosyć oczywiste, bo nie jest wtedy zmienną globalną :) Przy czym istnieje wyjątek - lokalne zmienne statyczne również inicjowane są na 0.


    Tylko, że ja pisałem o tym wyjątku tzn statycznych wewn. funkcji. Ale koniec końców to mogło być nieprecyzyjne bo przecież zmienna globalna opatrzona przydomkiem static to nie to samo co zmienna lokalna opatrzona przydomkiem static. (tzn static oznacza co innego w tych 2 przypadkach)
  • Pomocny post
    #7 8858019
    Dżyszla
    Poziom 42  
    tmf napisał:
    Dżyszla napisał:
    Zależne od kompilatora, a czasem wręcz od jego ustawień. Dobrym nawykiem jest inicjować nawet wtedy, gdy nie ma takiej potrzeby w danym środowisku.


    Nieprawda. Wszystkie zmienne globalne są domyślnie zainicjowane wartością zero, niezależnie czy są to typy proste czy złożone. Wynika to wprost ze standardu języka c.
    1. Wtedy jeszcze jednoznacznie nie było wskazania na C.
    2. Standardy standardami, a czy nie pojawią się kompilatory odbiegające od nich - nie można być pewnym.
    3. Kolejność inicjalizacji zmiennych globalnych jest przypadkowa, więc w pewnych specyficznych sytuacjach zmienna globalna faktycznie może jeszcze nie być zainicjalizowana, gdy zostanie używa.
  • Pomocny post
    #8 8858132
    tmf
    VIP Zasłużony dla elektroda
    ad 1. A wg ciebie składnia, którą przedstawił może występować w jakim innym języku?
    ad 2. Jeśli coś nie spełnia standardu języka to nie jest kompilatorem tego języka. Każde odstępstwa są udokumentowane. Kompilator, który w tak podstawowej rzeczy wykazywałby odstępstwa nie byłby w stanie stworzyć funkcjonalnego kodu.
    ad 3. A konkretnie w jakich sytuacjach? Przed rozpoczęciem wykonywania programu wszystkie struktury danych muszą być zainicjowane. jedyną możliwością, aby było inaczej jest wykorzystanie rozszerzeń kompilatora i linkera, np. w przypadku avr-gcc wykorzystanie sekcji .init poniżej 3.
  • Pomocny post
    #9 8858488
    hotdog
    Poziom 26  
    Był gdzieś niedawno dość długi temat o tym. IMO lepiej zawsze zmienne zerować dla czytelności, a w przypadku AVR-GCC po włączeniu optymalizacji te zbędne zerowania zostaną przez kompilator wycięte.

    Poza tym, dziwnie trochę ludzie wykorzystują słowo kluczowe volatile. W Twoim przypadku IMO nie powinno się stosować go wewnątrz struktury. Ostatnio widziałem, że ludzie często wszystkie zmienne globalne/struktury deklarują jako volatile (bo gdzieś przeczytali, że bez tego może nie działać), co mimo że działa jest błędem w sztuce. Tylko te zmienne zmieniane w przerwaniach powinny być zadeklarowane jako owe volatile.
  • Pomocny post
    #10 8858678
    tmf
    VIP Zasłużony dla elektroda
    Z tym volatile w tym przypadku to pewne przegięcie, bo zarówno pola struktury (czemu nie sama struktura?), jak i zmienna o tym typie są volatile, co jest lekko bez sensu, acz nie jest błędem. Natomiast nie zgodzę się, że volatile nie powinno się definiować wewnątrz struktury. Jeśli dane pola wskazują np. na zasoby sprzętowe, albo w inny sposób ze swej natury są volatile to użycie tego modyfikatora jest dobrą praktyką - ustrzega programistę przed błędem. Sugerując się nazwą, myślę, że w tym przypadku taka sytuacja zachodzi - stad IMHO użycie tych modyfikatorów jest być może uzasadnione.
    Swoją drogą nie tylko zmienne wykorzystywane w przerwaniach muszą być volatile, gdyby to było takie proste to już dawno byłoby automatycznie zaimplementowane w gcc. Z drugiej strony, są sytuacje, kiedy zmienne wykorzystywane w przerwaniach i innych częściach programu wcale volatile być nie muszą.
  • #11 8858870
    Fajfer2
    Poziom 20  
    Dodałem zerowanie jawnie w programie. Zmienne są volatile z racji użycia ich w przerwaniach i w programie "main".

    Dzięki i temat będzie można zamknąć.
  • Pomocny post
    #12 8858942
    janbernat
    Poziom 38  
    A co piszą w FAQ do tego?
    "
    Shouldn't I initialize all my variables?

    Global and static variables are guaranteed to be initialized to 0 by the C standard. avr-gcc does this by placing the appropriate code into section .init4 (see The .initN Sections). With respect to the standard, this sentence is somewhat simplified (because the standard allows for machines where the actual bit pattern used differs from all bits being 0), but for the AVR target, in general, all integer-type variables are set to 0, all pointers to a NULL pointer, and all floating-point variables to 0.0.

    As long as these variables are not initialized (i. e. they don't have an equal sign and an initialization expression to the right within the definition of the variable), they go into the .bss section of the file. This section simply records the size of the variable, but otherwise doesn't consume space, neither within the object file nor within flash memory. (Of course, being a variable, it will consume space in the target's SRAM.)

    In contrast, global and static variables that have an initializer go into the .data section of the file. This will cause them to consume space in the object file (in order to record the initializing value), and in the flash ROM of the target device. The latter is needed since the flash ROM is the only way that the compiler can tell the target device the value this variable is going to be initialized to.

    Now if some programmer "wants to make doubly sure" their variables really get a 0 at program startup, and adds an initializer just containing 0 on the right-hand side, they waste space. While this waste of space applies to virtually any platform C is implemented on, it's usually not noticeable on larger machines like PCs, while the waste of flash ROM storage can be very painful on a small microcontroller like the AVR.

    So in general, variables should only be explicitly initialized if the initial value is non-zero.

    Note:
    Recent versions of GCC are now smart enough to detect this situation, and revert variables that are explicitly initialized to 0 to the .bss section. Still, other compilers might not do that optimization, and as the C standard guarantees the initialization, it is safe to rely on it."
    Czyli w starszej wersji tracimy trochę pamięci a nowsze są dość inteligentne aby to poprawić.
  • Pomocny post
    #13 8859013
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Warto jeszcze w takim razie robić następujące rzeczy:
    1. po wejściu do przerwania wyłączać zezwolenie na przerwania
    2. przed wyjściem z przerwania włączać zezwolenie na przerwania
    3. zmienne globale inicjalizować wartością w kodzie
    4. ręcznie zachowywać rejestry przy wejściu do funkcji
    5. ręcznie przywracać rejestry przed wyjściem z funkcji
    6. wszystkie zmienne zrobić volatile
    7. nie korzystać z #define tylko wartości wpisywać ręcznie
    8. ...
    Na pewno znajdzie się jeszcze trochę rzeczy, które nie mają sensu, ale można je zrobić profilaktycznie, dla pewności i dla spokoju. Przecież nigdy nie wiadomo kiedy sprzęt albo kompilator się pomylą, więc lepiej przewidzieć wszystko i zapobiegać u źródła.

    4\/3!!
  • Pomocny post
    #14 8859331
    janbernat
    Poziom 38  
    Nie, Freddie nie o to mi chodziło- warto poszukać i przeczytać dokumentację.
  • Pomocny post
    #16 8859355
    mirekk36
    Poziom 42  
    No dokładnie jak pisze Freddy , ja już widzę taki kod jak to niektórzy na tzw wszelki wypadek inicjalizują sobie zerami wszystkie zmienne globalne, ba nawet struktury itp .... szczgólnie gdy program jest spory. To czysty jakby bezsens ;) a tym bardziej jeszcze jeżeli tylko niektóre z nich ktoś miałby inicjalizować zerem tak na wszelki, wszelki, wszelki wypadek albo liczyć na to że optymalizacja to i tak wywali z kodu. Nawet jeśli wywali to sam kod staje się przez to bardziej monstrualny i świadczy o tym, że ktoś właśnie nie doczytał jak to się dzieje ze zmiennymi globalnymi w C.
  • #17 8859821
    Fajfer2
    Poziom 20  
    Ok, w takim razie usunę zbędny kod inicjujący zmienne globalne (do wartości 0)
REKLAMA