Forum: Compiler & IDEs char*char=int ?


von Benedikt (Gast)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

> oder muss ich vorher auf int casten

Ja.

von Benedikt (Gast)


Lesenswert?

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 ?

von Alex (Gast)


Lesenswert?

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.

von A.K. (Gast)


Lesenswert?

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.

von A.K. (Gast)


Lesenswert?

"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.

von Benedikt (Gast)


Lesenswert?

@A.K.

Könntest du diese letzte Behaupt etwas genauer erklären ?

von A.K. (Gast)


Lesenswert?

@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.

von Benedikt (Gast)


Lesenswert?

Abgesehen von der char/int Ausnahme, gilt meine Aussage jedoch, oder ?

von A.K. (Gast)


Lesenswert?

Welche Aussage? Von derjenigen abgesehen, die ich bereits kommentierte,
finde ich keine.

von A.K. (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.