char*char=int ?

Gast #238774
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.
Gast
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 ?
Gast
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.
Gast
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.
Gast
"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.
Gast
@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.
Gast
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 21 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.