Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - FAQ - Zum CC1-Forum - Zum CC-Pro-Forum

Re: if-Abfrage bei Datentyp int Kategorie: Programmierung (von André H. - 15.06.2009 10:12)
Als Antwort auf Re: if-Abfrage bei Datentyp int von Wilfried - 15.06.2009 8:26
Ich nutze:
C-Control II Unit, C164CI-ControllerBoard, C-Control II Station, CC2-Application-Board, CC2-StarterBoard, CC2-ReglerBoard, OSOPT V3.1
Hallo Wilfried,

> > >   int crc;
> > >   crc = 0x8000;
> > >   if (crc == 0x8000) hwcom.print ("OK");
> > >   else                    hwcom.print ("Error");
> > >
> > > ergibt: "Error"
> > >
...

> Danke für Deine Antwort.
> Ich kann Deiner Erklärung jedoch nicht zustimmen, da die Operation "==" eine reine Vergleichsoperation
> ist. Da darf der Wertebereich, bzw. wie die Zahl zu interpretieren ist, keine Rolle spielen.
> Ich vermute, daÃ? da im Betriebssystem ein Bug ist.

Es ist schon etwas anmaÃ?end hier von einem Bug im OS zu sprechen.
Dem ist eindeutig nicht so.

nitraM hat Dir bereits die richtige Antwort, auch wenn in Kurzform, gegeben.

Das Programm macht genau das, was Du geschrieben hast und funktioniert auch korrekt.
Um zu verstehen, warum das korrekt ist, muÃ? man etwas die Grundlagen in C2 studieren:
1. Datentypen
  Ganzzahldatentypen gehen bis 32Bit Longinteger. Diese werden auch ggf. verwendet.
  Der Compiler entscheidet hier, ob ein konstanter Ausdruck als Integer oder
  als Longinteger zu behandeln ist. Dies geschieht anhand des Wertes.
  Von -32768 bis +32767 ist es ein Integer. Alles auÃ?erhalb dieses Bereichs ist Longintger.
2. Vergleichsoperatoren funktionieren in C2 immer Arithmetisch.
3. Sind in arithmetischen Funktionen mehrere unterschiedliche Datentypen beteiligt, versucht
  der Compiler dies durch Cast-Anweisungen auszugleichen.

0x8000 ist kein Integer sondern ein Longinteger, da dies hier die positive Zahl 32768 darstellt,
und nicht -32768. -32768 müsste hier als -0x8000 geschieben werden.
In C2 gibt es mit Ausnahme von Byte nur vorzeichenbehaftete Datentypen.
Daher mu� auch bei Hexadezimalen und Binärzahlen als Konstanten ein Vorzeichen vorangestellt
werden, wenn negative Integerzahlen gemeint sind, und diese später nicht
einer Integervariable zugewiesen werden.

Bei Deinem Vergleich ist einfach folgendes passiert:
"crc" ist Integer, 0x8000 ist vom Typ Long. Damit hier ein Vergleich stattfinden kann, wird
ein hier VM_EQU mit dem Zusatz CALC_INT_LONG kompiliert.
Aus dem Wert -32768 von crc, was binär 0x8000 entspricht, behandelt VM_EQU dabei
als  0xFFFF8000, was ebenfalls dem Wert -32768 entspricht. Eben nur als Long.
Nun soll dies mit 0x00008000 verglichen werden. Der Vergleich kann nicht True werden.

Es gibt hier mehrere Möglichkeiten, einen Integer zu erzwingen:
Die erste habe ich bereits genannt. Stelle bei allen Konstanten, bei denen Bit15 gesetzt ist und
keine höheren Bits gesetzt sind, ein Minus vor. Der Compiler behandelt die Zahl dann
as 16Bit-Integer.
Eine weitere Möglichkeit ist, da� die Konstante vorher einer Integervariable zugewiesen wird,
und die Variable beim Vergleich verwendet wird.
Dir dritte Möglichkeit wäre das gezielte Anwenden von Cast:
if (crc == cast.longInt(0x8000)) ...
Falls hier versucht wird diesesn Cast auf einen Integerwert anzuwenden, fügt der Compiler
vorher einen weiteren Cast ein, um den Wert ggf. vorher auf Long zu setzen.

Um das zu veranschaulichen:
thread main
{
 int crc;
 crc = 0x8000;
 if (crc == cast.longInt(0x7000)) crc=0x8000;
 else                    crc=0x100;
}


Dies ergibt folgende VM-Codes:
131 2 137 20 26 152 0 144 0 134 28672 24 26 74 133 7
137 22 26 152 0 132 4 134 256 152 0 132 65509

- (131) Stackpointer um 2 Byte erhöhen = Variable crc anlegen
- (137) Long-Konstante von Byte 20 laden
- (26) Cast Long zu Int
- (152) Ergebnis in Stackvariable 0 (Int) speichern (crc)
- (144) Stackvariable 0 (Int) laden (crc)
- (134) Direkte Integer-Konstante 0x7000 (28672) laden
- (24) Cast Int zu Long
- (26) Cast Long zu Int
- (74) VM_EQU = Vergleich durchführen
- (133) VM_BRANCH_IF_ZERO=Springe bei False 7 Wordcods weiter
- (137) Long-Konstante von Byte 22 laden
- (26) Cast Long zu Int
- (152) Ergebnis in Stackvariable 0 (Int) speichern (crc)
- (132) VM_BRANCH = Springe 4 Wordcodes weiter
- (134) Direkte Integer-Konstante 0x100 (256) laden
- (152) Ergebnis in Stackvariable 0 (Int) speichern (crc)
- (132) VM_BRANCH = Springe 27 Wordcodes zurück (65509=0xFFE5=-27)

Ich hoffe, das dient dem Verständnis, wie der Compiler mit Zahlen umgeht.

MfG André H.



Antworten bitte nur ins Forum!
Fragen per EMail auf Forum-Postings werden nicht beantwortet!

Das macht meine Heizung gerade


    Antwort schreiben


Antworten:

Re: if-Abfrage bei Datentyp int (von Wilfried - 15.06.2009 12:47)