Skocz do zawartości
ethanak

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

Udostępnij ten post


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

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
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

Udostępnij ten post


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

Udostępnij ten post


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

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
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

Udostępnij ten post


Link to post
Share on other sites
14 minut temu, dambo napisał:

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

OK - mój błąd.

Udostępnij ten post


Link to post
Share on other sites

Dyskusja została wydzielona z innego tematu od poniższego miejsca:

Zachęcam do kontynuowania rozważań w tym wątku 🙂

Udostępnij ten post


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:-))).

Udostępnij ten post


Link to post
Share on other sites

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!

Gość
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...