Forum: Compiler & IDEs Datentypen und Berechnungen


von bal (Gast)


Lesenswert?

Hallo, eine kurze Frage, die mir gerade durch den Kopf geistert:

Eine Berechnung wird immer in der Breite des größten beteiligten 
Datentypen durchgeführt. Mindestens aber in INT.
Der Datentyp der links vom "=" steht spielt dabei keine Rolle.
Deswegen funktinoiert beim ATmega auch:
uint8_t a = 5;
uint8_t b = 3;
uint16_t c = a * b;

Ohne dass Casts notwendig sind.
(Mal davon abgesehen dass der Compiler hier bei Konstanten eh selber 
rechnen wird)

Aber wieso kann der Compiler dann aus "a + b" einen einfachen 
"add"-Befehl machen, der ja nur 8 Bit werte addiert?

von Peter II (Gast)


Lesenswert?

bal schrieb:
> Aber wieso kann der Compiler dann aus "a + b" einen einfachen
> "add"-Befehl machen, der ja nur 8 Bit werte addiert?

kann er das denn? Woher weisst du das er das macht?

von (prx) A. K. (prx)


Lesenswert?

bal schrieb:
> Aber wieso kann der Compiler dann aus "a + b" einen einfachen
> "add"-Befehl machen, der ja nur 8 Bit werte addiert?

Er muss sich so verhalten, als ob entsprechend der Definition 
gearbeitet wird. Weiss er jedoch, dass in optimierter Form das gleiche 
Ergebnis raus kommt, dann darf er abkürzen. Also vereinfacht:
   uint8_t  a, b;
   uint16_t c = a + b; // 16bit Rechnung nötig
   uint8_t  d = a + b; // 8bit Rechnung zulässig

von bal (Gast)


Lesenswert?

Peter II schrieb:
> kann er das denn? Woher weisst du das er das macht?

Weil er mir
uint8_t test2(uint8_t a, uint8_t b)
{
  return a + b;
}

in

  92:  86 0f         add  r24, r22
  94:  08 95         ret

übersetzt.

@ A.K.:
Macht Sinn. Ich ging bisher davon aus dass nur die an der Berechnung 
beteiligten Datentypen eine Rolle spielen.

Die Zuweisung danach ist wieder ein anderes Thema...

von bal (Gast)


Lesenswert?

Hm, ohne Optimierung wird der Code viel länger:

uint8_t test2(uint8_t a, uint8_t b)
{
  92:  df 93         push  r29
  94:  cf 93         push  r28
  96:  00 d0         rcall  .+0        ; 0x98 <test2+0x6>
  98:  cd b7         in  r28, 0x3d  ; 61
  9a:  de b7         in  r29, 0x3e  ; 62
  9c:  89 83         std  Y+1, r24  ; 0x01
  9e:  6a 83         std  Y+2, r22  ; 0x02
  return a + b;
  a0:  99 81         ldd  r25, Y+1  ; 0x01
  a2:  8a 81         ldd  r24, Y+2  ; 0x02
  a4:  89 0f         add  r24, r25
}
  a6:  0f 90         pop  r0
  a8:  0f 90         pop  r0
  aa:  cf 91         pop  r28
  ac:  df 91         pop  r29
  ae:  08 95         ret

Bin ja nicht sooo fit in Assembler, aber die Berechnung ist doch immer 
noch in 8Bit. Lediglich der Funktionsaufruf macht mehr Arbeit.

von (prx) A. K. (prx)


Lesenswert?

bal schrieb:
> Macht Sinn. Ich ging bisher davon aus dass nur die an der Berechnung
> beteiligten Datentypen eine Rolle spielen.

Formal gesehen liegst du richtig. Formal muss er so tun, als ob er in 
"int" rechnet. Aber wenn er am Kontext erkennt, dass das ausser Aufwand 
nix einbringt, dann gehts auch eine Nummer kleiner.

So darf er bei
  uint8_t e = (a + b) / 2;
nicht in 8 Bits rechnen, weil das Ergebnis nicht durchweg identisch ist.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

bal schrieb:

> Weil er mir

nicht nur dir ;-)

> uint8_t test2 (uint8_t a, uint8_t b)
> {
>   return a + b;
> }
>
> in
>
>   92:  86 0f         add  r24, r22
>   94:  08 95         ret
>
> übersetzt.

a + b ist ein 16-bit Wert, jedoch wird von test2 nur ein 8-Bit Wert 
returniert.  Dies ist so sein das ABI geändert wurde, irdendwo zwischen 
GCC Version 4.2 und 4.3 wenn ich mich recht entsinne: Es gibt keine 
Promotion von 8-Bit Werten zu 16-Bit Werten mehr.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

...und es gibt sogar eine AVR-LibC Anforderung die ABI-Doku dahingehend 
anzupassen:

http://savannah.nongnu.org/bugs/?37026

von troll (Gast)


Lesenswert?

A. K. schrieb:
> Weiss er jedoch, dass in optimierter Form das gleiche
> Ergebnis raus kommt, dann darf er abkürzen. Also vereinfacht:
>    uint8_t  a, b;
>    uint8_t  d = a + b; // 8bit Rechnung zulässig

demnach ist das hier

bal schrieb:
> uint8_t test2(uint8_t a, uint8_t b)
> {
>   return a + b;
> }
>   92:  86 0f         add  r24, r22
>   94:  08 95         ret

doch vollkommen in Ordnung?! Oder hab ich nen Knoten im Hirn?

von Rolf M. (rmagnus)


Lesenswert?

bal schrieb:
> Ich ging bisher davon aus dass nur die an der Berechnung beteiligten
> Datentypen eine Rolle spielen.

Das ist auch so. Teil der C-Norm ist aber auch die sogenannte 
"as-if"-Regel. Diese besagt, daß der Compiler von deinem Code beliebig 
abweichen darf, solange das beobachtbare Verhalten ("observable 
behavior") gleich bleibt. Der Optimizer erkennt, daß eine Rechnung in 8 
Bit gegenüber der in 16 Bit am Ergebnis nichts ändert, also darf er die 
Vereinfachung laut as-if-Regel machen.

von Fabian H. (Firma: Technische Universität Berlin) (brein)


Lesenswert?

Johann L. schrieb:
> a + b ist ein 16-bit Wert, jedoch wird von test2 nur ein 8-Bit Wert
> returniert.  Dies ist so sein das ABI geändert wurde, irdendwo zwischen
> GCC Version 4.2 und 4.3 wenn ich mich recht entsinne: Es gibt keine
> Promotion von 8-Bit Werten zu 16-Bit Werten mehr.

Mal für einen Noob wie mich, weil es mich interessiert:
Was ist das ABI
und
was versteht man unter Promotion bei den Datentypen?

Vielen Dank
Fabian

von Rolf M. (rmagnus)


Lesenswert?

Fabian Hoemcke schrieb:
> Johann L. schrieb:
>> a + b ist ein 16-bit Wert, jedoch wird von test2 nur ein 8-Bit Wert
>> returniert.  Dies ist so sein das ABI geändert wurde, irdendwo zwischen
>> GCC Version 4.2 und 4.3 wenn ich mich recht entsinne: Es gibt keine
>> Promotion von 8-Bit Werten zu 16-Bit Werten mehr.
>
> Mal für einen Noob wie mich, weil es mich interessiert:
> Was ist das ABI

http://de.wikipedia.org/wiki/Binärschnittstelle

> und was versteht man unter Promotion bei den Datentypen?

http://de.wikipedia.org/wiki/Promotion_(Typumwandlung)

von (prx) A. K. (prx)


Lesenswert?

troll schrieb:
> doch vollkommen in Ordnung?!

Ja.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.