char HEX-Problem, warum 16 Bit breit

Hallo Gemeinschaft,

ich habe hier ein kleines Programm das am Seriellen Port Daten empfängt.
Das klappt schon mal sehr gut.

Mein Empfangspuffer ist so vereinbart:

const int MaxEmpfangsZeichen = 199;
char Emfangszeichenkette[MaxEmpfangsZeichen + 1]; // immer eins mehr
int ZaehleEmpfangzeichen = 0;

hier die Empfangsroutine:
void serialEvent() {
while (Serial.available()) {
byte inChar = Serial.read();
if (ZaehleEmpfangzeichen < MaxEmpfangsZeichen - 2) {
Emfangszeichenkette[ZaehleEmpfangzeichen++] = inChar;
}
}
}

In den Empfangenen Zeichen kann auch 0FEh (Hexadezimal) vorkommen.
Wenn ich mit einer Schleife durch die empfangenen Zeichen gehe und sie vergleiche
finde ich 0xFE nicht !?!?

for (int n = 2; n < ZaehleEmpfangzeichen; n++) {
if (Emfangszeichenkette[n] == 0xFE) {

auch folgende Konstruktion hilft nicht:

for (int n = 2; n < ZaehleEmpfangzeichen; n++) {
if (Emfangszeichenkette[n] & 0x00FF == 0xFE) {

suche ich nach 0xFFFE, dann ist es wahr !

for (int n = 2; n < ZaehleEmpfangzeichen; n++) {
if (Emfangszeichenkette[n] == 0xFFFE) {

ich habe ja char = 8 Bit deklariert, woher kommen dann die oberen 8 Bit FFxx ? also ein word ?

Bemerkung: Die Schleife beginnt bei 2 da die ersten beiden Zeichen nie FE sein können.

Danke für jeden Tip.

Gruß Melmac

int        ZaehleEmpfangzeichen

Das sind zwei Bytes.

EDIT 22.11.2017: Die Aussage war gut gemeint, ist aber leider nicht hilfreich. Sorry :confused:

Dann mach mal aus byte Empfangszeichenkette unsigned Byte. oder vergleiche statt mit 0xFE mit (char) oder besser
(unsigned char) 0xFE.

Deine Konstante ist von Typ int. Bei Operationen wird immer auf die Kardinalität des größten Datentyps erweitert.
Also ein Element aus Empfangszeichenkette wird umgewandelt von char auf int.
Da du aber signed char hast ist bei 0xFE das Vorzeichenbit gesetzt also wir haben den Wert -2 Das expandiert
auf int gibt 0xFFFE also auch -2.

Sind die Datentypen unsigned dann ist 0xFE 254 und auch als int 254 also 0x00FE.
Je nach Compiler kann man sich bei char nicht darauf verlassen ob signed char oder unsigend char die
Voreinstellung ist. Also immer "ausformulieren".

Ulli

ich habe ja char = 8 Bit deklariert, woher kommen dann die oberen 8 Bit FFxx ? also ein word ?

Empfangszeichenkette[n] ist ein char, da hast du Recht.
0xFE ist aber einint

Der Vergleich == wird daher mit zwei int gemacht.

char c = 0xFE; ist vorzeichenbehaftet. Also -2 oder als int gesehen das gleiche wie 0xFFFE;
const int i = 0xFE; ist natürlich 254, und damit ungleich -2

Wenn es dich tröstet: du bist nicht der einzige, dem das erst beim Testen auffällt.

@agmue, ZaehleEmpfangzeichen ist nur der Zähler wie viele Zeichen in meinem Puffer (Array) stehen
und hat damit nichts zu tun.

@beeblebrox, @michael_x
das ist die Lösung, man muß schon so einige kleine Schweinereien der Compiler wissen ...
lernt man aber mit der Zeit. :wink:

Danke vielmals an dieser Stelle

Gruß Melmac

Das sind aber keine (kleinen oder großen) Schweinereien des Compilers, das sind (fehlende) Grundkenntnisse.

Gruß Tommy

Hi

Trotz der fehlenden Grundkenntnisse wäre der Vergleich in ASSEMBLER 'völlig Banane' - da ist 0xFE == 0xFE, fertig!
Einzig beim Rechnen macht sich das Vorzeichen bemerkbar - vll. wurden hier einfach Grundlagen gemacht, wo Keine nötig gewesen wären - aber da die Sprache schon etwas älter ist, wohl so eingebürgert.

Trotzdem 'nice²know' - man kann (will) halt nicht Alles in Assembler erschlagen - auch, weil man da doch mehr an die Zielhardware gebunden ist.

MfG

Wo siehst Du hier Assembler?

Gruß Tommy

Hi

Ich schrieb, daß in Assembler die Prüfung von 0xFE mit 0xFE true ergibt - da es dem Assembler egal ist, was für ein Typ dieses 0xFE ist - dafür hast Er einen Programmierer - Der kümmert sich darum, daß das 0xFE Das ist, was Es sein soll.
Dort kann ich auch 0x31 mit "1" vergleichen und bekomme true raus - Gleiches will mir der Arduino gerade nicht machen, da ich ein byte mit einem char vergleichen will (wenn ich mich recht entsinne).

Ich schrieb auch nicht, daß Das in Assembler kein Problem wäre oder Ähnliches - ich schrieb, daß das Problem in Assembler kein Problem wäre - schrieb ich aber oben schon.

MfG

In Assembler kann man noch viel blödere Fehler machen, zumal es in AVR-Assembler gar keinen int Datentyp gibt, höchstens Register einzeln und im Doppelpack.

Ob man in Assembler 100 oder 1000 mal mehr Fehlermöglichkeiten hat, die erst beim Testen auffallen, darüber will ich jetzt mal nicht streiten.

Der größte Fehler ist immer, Assembler zu verwenden, obwohl es nicht nötig wäre.
Und es ist nur ganz selten nötig.
Der wichtigste Anwendungsfall für Assembler ist

  asm volatile (" nop "); // Warte einen Takt