Wenn ich auf einem AVR (oder vermutlich auch den meisten anderen 8bit uCern) zwei Bytes multipliziere bekomme ich ein Doppelbyte, also einen int. Wie ist das jetzt in C ? Normalerweise wird doch nur mit den Datentypen gerechnet die vorhanden sind, also char+char=char, int+char=int usw. und erst bei der Zuweisung wird der Datenytp konvertiert. Was passiert also, wenn ich int=char*char in C rechne, funktioniert das oder muss ich vorher auf int casten (was ja eigentlich Schwachsinn wäre, denn der Compiler rechnet dann int=int*char obwohl char*char ausreichen würde.
Mit WinAVR ist es egal ob am castet oder nicht, es wird ein int daraus, das Ergebnis passt also. volatile unsigned char x,y; volatile unsigned int z; z=x*y; 67 0008 9981 ldd r25,Y+1 68 000a 8A81 ldd r24,Y+2 69 000c 989F mul r25,r24 70 000e C001 movw r24,r0 71 0010 1124 clr r1 72 0012 8B83 std Y+3,r24 73 0014 9C83 std Y+4,r25 Ist das eine Eigenart von dem Compiler, oder gibt es irgendwie was festgelegtes ?
Komisch, bei shift-Operationen meckert der Compiler, wenn man nicht vorher castet (was ja auch so sein muß) ... unsigned char x = 0xAA; x <<= 8; Wird angemeckert. unsigned char x = 0xAA; unsigned int y = 0; y = (unsigned int) x << 8; Ist i.O.
Jeder ANSI-C Compiler muss sich bei "char" Operationen so verhalten,
als ob beide Seiten der Operation erst nach "int" konvertiert werden
und danach gerechner wird. Das ist in C so definiert. Wenn's in der
Praxis auch kürzer geht und der Compiler spezielle Operationen auch
nutzt (8x8=16 MUL), dann ist das ok, wenn das Ergebnis muss zur
Definition passt.
Typische Falle in diesem Zusammenhang:
uint8_t x;
if (x+1 > 100)
Ein ANSI-C-Compiler muss das auch wirklich als 16-Bit Operation
durchführen. Weil's im Fall x=255 auf die Varianten (0 > 100) vs (256
> 100) rausläuft. Wer da unbedingt effizienten 8-Bit-Code haben will,
muss schreiben:
if ((uint8_t)(x+1) > 100)
@Alex: Es bleibt dem Compiler unbenommen, Blödsinn auch als Blödsinn zu
bezeichnen, wenn er in der Lage ist, das zu erkennen.
Der erste Fall (x <<= 8) ist formal
x = (char)( (int)x << 8 )
und damit wirkungsmässig identisch mit
x = 0
Es spricht nichts dagegen, dass der Compiler das merkt. Muss er aber
nicht.
Der zweite Fall ist jedoch völlig in Ordnung.
"Normalerweise wird doch nur mit den Datentypen gerechnet die vorhanden sind, also char+char=char, int+char=int usw. und erst bei der Zuweisung wird der Datenytp konvertiert." Nein.
@Benedikt: Habe ich doch oben geschrieben: Jeder ANSI-C Compiler muss sich bei "char" Operationen so verhalten, als ob beide Seiten der Operation erst nach "int" konvertiert werden und danach gerechner wird. Ist seit K&R so festgelegt und wurde weder von ANSI noch von C++ geändert. Historischer Hintergrund: C ist für die PDP-11 entstanden und die Byte-Operationen der PDP-11 arbeiten so. Der Compiler kann natürlich a=b+c immer noch 8bittig rechnen, denn wenn a,b,c 8bittig sind, kommt exakt das gleiche dabei heraus. Es gibt freilich Compiler, die dieses Verhalten abschaltbar machen (z.B. Keil), weil's auf 8bittern etwas ineffizient ist. Näheres dazu siehe C-Handbuch.
Welche Aussage? Von derjenigen abgesehen, die ich bereits kommentierte, finde ich keine.
C Handbuch siehe "type coercion" oder "usual arithmetic conversions". Hab's nicht auf deutsch parat, sorry. Kurzform: Es werden sowohl die Operanden aneinander angepasst erweitert, als auch das Ergebnis anschliessend an den Typ des Zieloperandens erweitert oder reduziert. Die Operation findet mindestens als "int" oder "unsigned" statt, char/short-Werte werden entsprechen erweitert.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.