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?
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?
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
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...
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.
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.
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.
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?
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.
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
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 ABIhttp://de.wikipedia.org/wiki/Binärschnittstelle> und was versteht man unter Promotion bei den Datentypen?http://de.wikipedia.org/wiki/Promotion_(Typumwandlung)