Skocz do zawartości

Różnica między #define, a const int


Pomocna odpowiedź

Nie zauważyłeś, że tu nie ma nieużywanych śmieci. Przy dokładnie takich samych opcjach jak Twoje mam:

$ avr-size sg1.elf
   text	   data	    bss	    dec	    hex	filename
    214	      2	      0	    216	     d8	sg1.elf
$ avr-size sg2.elf
   text	   data	    bss	    dec	    hex	filename
    188	      0	      0	    188	     bc	sg2.elf

 

  • Lubię! 1
Link to post
Share on other sites

To chyba udało ci się w końcu oszukać kompilator. W sumie to wiara w moc optymalizacji jest ułomna, a jak widać na załączonym obrazku nawet prosty program może przechytrzyć kompilator.

A tak z ciekawości - gdyby zamiast const użyć constexpr to kod byłby taki sam w obu przypadkach? Może należy jednak polubić C++11 albo wrócić do stylu C.

  • Lubię! 1
Link to post
Share on other sites
1 godzinę temu, Elvis napisał:

A tak z ciekawości - gdyby zamiast const użyć constexpr to kod byłby taki sam w obu przypadkach? Może należy jednak polubić C++11 albo wrócić do stylu C.

Zmieniłem dwie rzeczy w kodzie @ethanak : const na constepr, reszta pozostaje identyczna:

//testy1.h:

extern void pinOn(void);
constexpr int PIN = 7;
extern void digitalWrite(int, int);
// sc1.cpp

#include "testy1.h"

// const int PIN = 7;
int main(void)
{
    pinOn();
}


Budowanie ze wsparciem dla C++11:

avr-gcc -std=c++11 -Os -Wl,--gc-sections -mmcu=atmega328p -o s1.elf sc1.cpp sd1.cpp dw.cpp
avr-gcc -std=c++11 -Os -Wl,--gc-sections -mmcu=atmega328p -o s2.elf sc2.cpp sd2.cpp dw.cpp

avr-size s1.elf  
   text    data     bss     dec     hex filename
    188       0       0     188      bc s1.elf
    
avr-size s2.elf
   text    data     bss     dec     hex filename
    188       0       0     188      bc s2.elf

Jak widzimy przy wykorzystaniu constexpr osiągamy ten sam plik wynikowy co przy #define.

* dodatkowo, gdy wyrzucimy extern z pliku testy1.h i zadeklarujemy i zdefiniujemy const int PIN = 7; znowu otrzymamy ten sam kod wynikowy co w przypadku użycia #define ale już bez konieczności używania C++11. Dlatego preferowaną metodą definiowania stałych w C++ jest definiowanie i deklarowanie ich w jednym miejscu.

Dla ciekawych możliwości nowoczesnego C++ polecam prezentację Jasona Turnera: “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17” którą można zobaczyć na youtube

Edytowano przez Matthew11
Dodanie uwag
  • Lubię! 1
Link to post
Share on other sites

@ethanak Wyszło, że dla jednego pliku działa tak jak reszta się spodziewała, więc "oszukałeś" i rozbiłeś to na oddzielne jednostki kompilacji przez co wymusiłeś żeby ta dana została - to inaczej nie mogło zadziałać - moduły zostały skompilowane tak, żeby tą wartość odczytać - więc tak to finalnie musiało być. Optymalizacja działa w obrębie jednostki kompilacji.

Sprawę załatwi link time optimalization - przy "szerszym spojrzeniu" linker zobaczy, że to jest const i inaczej to zrobi - finalnie nie będzie nic w sekcji data.

avr-gcc -flto -fdata-sections -ffunction-sections -c -o sc1.o sc1.cpp
avr-gcc -flto -fdata-sections -ffunction-sections -c -o sd1.o sd1.cpp
avr-gcc -flto -fdata-sections -ffunction-sections -c -o dw.o dw.cpp
avr-gcc -flto -Wl,-gc-sections -o s1.elf sc1.o sd1.o dw.o
avr-size s1.elf

Natomiast fajnie, że constexpr załatwia sprawę - warte zapamiętania.

[UPDATE]

A nawet trochę za daleko pojechałem - już wsadzenie tego w sekcję, bez - flto powoduje ten sam efekt.

Czyli chodziło mniej więcej o to co pisał Elvis wcześniej:

"Zapomniałeś o opcji dla linkera - bez niej nieużywane śmieci zostają w pamięci."

  • Lubię! 2
Link to post
Share on other sites
13 minut temu, dambo napisał:

"oszukałeś" i rozbiłeś to na oddzielne jednostki kompilacji

Wcale nie oszukiwałem! Po prostu zawsze staram się trzymać w jednym pliku konkretny fragment kodu.

LTO zadziała tylko jeśli wszystkie pliki kompilowane są jednocześnie - builder Arduino IDE kompiluje je oddzielnie, czyli nic nie zmieni.

  • Lubię! 1
Link to post
Share on other sites
6 minut temu, ethanak napisał:

LTO zadziała tylko jeśli wszystkie pliki kompilowane są jednocześnie - builder Arduino IDE kompiluje je oddzielnie, czyli nic nie zmieni.

Co rozumiesz przez "kompilowane są jednocześnie"?

[UPDATE]

Nawet teraz widzę, że LTO jest domyślnie uruchomione w arduino - może nie we wszystkich wersjach tak jest.

Edytowano przez dambo
  • Lubię! 1
Link to post
Share on other sites

Mnie tylko zaineresowało dlaczego autor wątku w jednym miejscu używa #define, a w innym const int.... więc piszecie, że to dyskusja akademicka...;) ale dobrze pozostać przy #define... mnie wystarczy:-))).

Link to post
Share on other sites
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.