Wpis z mikrobloga

Hej, ale mam zagwostkę ( ͡º ͜ʖ͡º). *Padniecie*!

Normalnie sobie piszę program w C++ (avr-g++) #atmega (dokładniej #xmega) no i mam funkcję, która przyjmuje tak daną:

funkcja(int liczba)
ale, że drugi raz patrzę na kod (a coś się w tym czasie nauczyłem) to chcę pomóc kompilatorowi i piszę:

funkcja(const int &liczba)
i czaicie, że rozmiar programu się zwiększył? I to z 2862 do 2886 bajtów!!!

No i teraz czy ja czegoś nie czaję, czy to nie normalne zachowanie jednak kompilatora?
Pomyślałem, może wyjątek, poprawiłem jeszcze jedną funkcję! I co? +4bajty do kodu ( ͡° ʖ̯ ͡°)

avr-g++ (GCC) 6.2.0

Copyright (C) 2016 Free Software Foundation, Inc.

This is free software; see the source for copying conditions. There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


#cplusplus #uc #mikrokontrolery dodam #linux bo to osoby które znają się na pamięci.
  • 18
@xaoc: nie mam pojęcia co tam się stało, ale mam pytanie, w jaki sposób chciałeś tutaj wprowadzić optymalizację? Rozumiem, że chodzi o zużycie pamięci. Zastosowanie referencji wymusi utworzenie wskaźnika, który i tak jest wielkości int'a więc nie powinno być żadnej różnicy. Cos pomyliłem?
@NiedzielnyMirek: Mówię kompilatorowi, żeby nie tworzył kopi obiektu(referencja) i że nie będę go modyfikował. A więc ma pewność, że od tego momentu wartość jest stała i się na 100% nie zmieni. Co za tym idzie w dalszych działaniach może wygenerować bardziej optymalny kod.

Dodatkowo chodzi o nawyk, nie będę używał na typach wbudowanych nie będę używał na klasach.
@pytonger: No właśnie problem w tym, że widać -- tzn. skoro i tak wskaźnik jest typu int to dla czego zwiększył rozmiar o 24 bajty? Nawet jeśli przyjmiemy, że int ma 2 bajty a adres 3 bajty (nie jestem specjalistą ale kojarzę, że ma jakieś specjalne adresy 24bitowe) to i tak się to kupy dupy nie trzyma.
@xaoc: zrób eksperyment i popraw na fn(const int liczba). Na ARM C Compiler mówi to kompilatorowi żeby podstawił po prostu adres zmiennej z argumentu na zasadziue stałej do funkcji fn. Jestem ciekaw co zrobi GCC.
@NiedzielnyMirek:

bool Serial::insert_int(const int i){
char buff[sizeof(int)*4]; // Works only with base 10
return this->insertStr(itoa(i, buff, 10));
}

@keton22: Ta wersja ma dokłdanie ten sam rozmiar co fn(int);
@pytonger: No właśnie a nie powinien przynajmniej w terorii.

Porobiłem kilka eksperymentów i czasem jest bardziej optymalnie czasem mniej. Jeśli chodzi o drogę w stronę optymalizacji to zyskuje 2 bajty. A w drugą stronę z reguły bierze dużo więcej.
@pytonger: Mi się zawsze wydawało, że referencja, jest czymś bardziej optymalnym od wskaźnika. A już na pewno nie potrzebuje kopi obiektu. Najwyraźniej się myliłem.
Co do

kod umożliwiający operowanie na wielu referencjach do tego samego obiektu.

to mi się wydaje, że referencja -- to jest inna nazwa na tą samą zmienną w związku z tym dlaczego miał by generować dodatkowy kod. I tak się kompilator posługuje głównie adresami.

O podam na
@xaoc: W przypadku nieinlinowanego kodu const& moƶe uniemoƶliwić część optymalizacji - np. trzeba po wykonaniu funkcji ponownie załadować wartość zmiennej z pamięci, bo jakaś funkcja dalej mogła wykonać const_cast i cała const-ność referencji psu w dupę.
@KrzaQ2: Nieliowego kodu? tzn. (nie inline)

A czy właśnie kompilator nie powinien sprawdzić, czy jakaś funkcja nie wywołała właśnie const_cast. Chodź przypuszczam, że śledzenie dostępu do zmiennej przekazywanej przez referecnję jest trudne.

Czyli wniosek jest taki -- referencja skraca kod jeśli kompilator może sprawdzić czy na danej zmiennej nie wykonano żadnego rzutowania.
@xaoc: Lekki skrót myślowy. Aby uznać, ƶe nie będzie const_cast, kompilator musi to formalnie udowodnić. Aby to zrobić, muszą być spełnione następujące warunki:

- kompilator musi widzieć kod funkcji (ew. linker jeśli mowa o LTO, ale nie wiem czy w tej fazie w ogóle takie coś się odbywa)
- drzewko wywołań musi być odpowiednio krótkie. Dopóki nie będzie dowodu na P=NP, takie drobnostki jak halting problem utrudniają sprawę. Kompilatory obecnie
@KrzaQ2: Czyli kompilator nie sprawdzi sobie funkcji, jeśli znajduje się w innym pliku? U mnie na pewno nie ma kilkuset wywołań -- bo jest to sam początek pisania.

Ale dzięki -- bardzo fajna strona.
@xaoc: Nie sprawdzi. Je​śli kompilatorowi mówisz "funkcja istnieje ale, hehe, jej nie widzisz" to on Ci ufa ;) Tak jak pisałem jest jeszcze LTO, ale jakie tam są optymalizacje to za bardzo nie wiem.
@xaoc: Na pewno nie ma to sensu dla typów mniejszych/równych rozmiarowi wskaźnika (bo do tego de facto sprowadza się referencja). Potem byś juƶ musiał benchmarkować, szczególnie, ƶe wielkość kodu i jego wydajność nie przekładają się 1:1
@KrzaQ2: To wiem, mi bardziej zależy na wielkości kodu -- Kod nie musi być bardzo optymalny, poza przerwaniami ale tam jest __attribute__((optimize("O2")))