Problem mit signed long aus 4 einzelnen Bytes

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
Bang-Johansen
Beiträge: 43
Registriert: 11. Juli 2011 22:51

Problem mit signed long aus 4 einzelnen Bytes

Beitrag von Bang-Johansen »

Hallo,

ich bin im Moment mit meinem Programmierlatein am Ende.
Folgender Fall:
ich möchte einen signed long aus 4 Bytes zusammensetzen.
Das mache ich so.
(Auszug)
in der .h

Code: Alles auswählen

struct
			{
		        ....
			long int	  ActualPosition;	
			.....
			}AxisXStatus; 	
(Auszug)
in der .cpp

Code: Alles auswählen

// 4 Byte in long konvertieren
// mit dem MSB beginnen und dann um ein Byte weiterschieben
AxisXStatus.ActualPosition =  ReceiveData [12];
AxisXStatus.ActualPosition =  (AxisXStatus.ActualPosition << 8);
AxisXStatus.ActualPosition |= ReceiveData [11];
AxisXStatus.ActualPosition =  (AxisXStatus.ActualPosition << 8);
AxisXStatus.ActualPosition |= ReceiveData [10];
AxisXStatus.ActualPosition =  (AxisXStatus.ActualPosition << 8);
AxisXStatus.ActualPosition |= ReceiveData [9];
			
qDebug () << ReceiveData [12] << "," << ReceiveData [11] << "," << ReceiveData [10] << "," << ReceiveData [9] << ":" << AxisXStatus.ActualPosition;
Das Problem ist nun, daß ich überhaupt keine negativen Werte bekomme:
Steht z.B. in den Bytes 0,0,0,4 -> erhalte ich in der Ausgabe durch qDebug 4 (OK)
Steht z.B. in den Bytes 255,255,255,250 -> erhalte ich in der Ausgabe durch qDebug 4294967290 (falsch)

Wenn ich vor qDebug die Variable AxisXStatus.ActualPosition auf -123435 setze, -> erhalte ich in der Ausgabe durch qDebug -1234435 (OK)
Wenn ich statt long int nur int benutze, ist die Anzeige auch korrekt,bloß int reicht mir natürlich nicht.
Ist bei long int nicht auch das höchste Bit das Vorzeichenbit ?
Habe schon signed davor geschrieben, brachte aber auch nichts.

Könnte mir bitte jemand sagen, was ich falsch mache ?

Danke Euch

Bang Johansen
ScyllaIllciz
Beiträge: 200
Registriert: 9. Juli 2010 19:31

Re: Problem mit signed long aus 4 einzelnen Bytes

Beitrag von ScyllaIllciz »

Irgendwie widerspricht sich Deine Vorstellung. Du hast 4 Bytes (int) und willst ein long int 8 Bytes. Willst Du mit den Werten weiter rechnen? Wenn nein, brauchst Du kein long int. Ansonsten musst Du erst ein int Wert erzeugen und diesen dann in eine long int casten, weil ein long int einen größeren Speicherbereich hat und somit ein Wert, der in einem int negativ ist, in einem long int noch lange nicht negativ ist.

Ich hoffe ich war etwas verständlich ;-)
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Problem mit signed long aus 4 einzelnen Bytes

Beitrag von RHBaum »

long int ist 64 bit (8 Byte) oder ?
int ist 32 bit (4 Byte)

ich nehm an wir programmieren auf nem lsb(intel) system ...
Ist bei long int nicht auch das höchste Bit das Vorzeichenbit ?
wär dann richtig, also wär das 64te ([63]) das vorzeichen-Bit
Mit deinen 4 Byte schiebeoberationen fuellst aber immer nur bis bit 32([31]) auf.
Das kann also nie negativ werden.

du musst also entweder selber abchecken ob bei deinem 4 byte das vorueichen bit gesetzt ist, darfst dann nur 31 bit kopieren und musst das vorzeichenbit selber beim 64er typ setzen.
Oder du baust zuerst ne 32 bit wariable und ueber zuweisung wandelst dann in ne 64bit variable, der macht das fuer dich dann ...

Anmerkung:
wenn du byteweisse Datenbeschreiben willst, wuerd ich nie 8fache shift operationen verwenden.
Besser:
uber casts:

Code: Alles auswählen

long int my64BitVar = 0; 
unsigend char * pBytePointer = reinterpret_cast<unsigend char *>(&my64BitVar);
/// nu kannst byteweisse direkt zugreifen 
pBytePointer[0] = 1;
pBytePointer[1] = 2;
std::cout << my64BitVar; 
oder ueber unions

Code: Alles auswählen

union
{
    long int 64BitValue;
    unsigend char charArray[8];
} myVar;

myvar.64BitValue = 0;
myvar.charArray[0] = 1;
myvar.charArray[1] = 2;

std::cout << myvar.64BitValue; 
bmann
Beiträge: 14
Registriert: 22. Juni 2006 22:27
Wohnort: Dortmund

Re: Problem mit signed long aus 4 einzelnen Bytes

Beitrag von bmann »

Hallo Bang Johansen,

wie ja schon korrekt beschrieben wurde, ist dein Problem mit ziemlicher Sicherheit, dass du 32 Bits in ein long int schreibst. Und hier fängt die Fragerei an: Auf was für einem System arbeitest du?
Ich nehme an auf einem 64 Bit Linux System. Auf dieser Plattform ist long int ein 64 Bit Datentyp (auf Linux 32 Bit oder auf Windows 32 und 64 Bit wäre long int nur 32 Bit, also identisch zu int).
Wenn du aber (wie du es machts) 255*2^24+255*2^16+255*2^8+250 rechnest, ergibt das 4294967290, was wunderbar in einen 64 Bit Datentyp passt, also wird es hier keine negativen Zahlen geben.

Du schreibst, dass ein int dir "natürlich nicht" reicht. Warum nicht?

Im übrigen würde ich, wenn du Dinge tust, die von der Bitzahl des Datentyps abhängen, gründsätzlich statt "int", "long int", etc. lieber qint32 und qint64 benutzen, das funktioniert dann auch auf anderen Plattformen. In deinem Fall also qint32.

Zum "Vorzeichenbit": Ja, das führende Bit bei 64 Bit Zahlen gibt an, ob es sich um eine positive oder eine negative Zahl handelt ("Vorzeichenbit" ist aber eigentlich nicht richtig, siehe Definition der 2er Komplement Darstellung). Genau deshalb hast du nur positive Zahlen, du schreibst ja nur in die untersten 32 Bit.

Gruß
Andi
Bang-Johansen
Beiträge: 43
Registriert: 11. Juli 2011 22:51

Re: Problem mit signed long aus 4 einzelnen Bytes

Beitrag von Bang-Johansen »

Hallo,

Ihr habt alle Recht !!!

Gestern Abend im Bett hatte ich auch die Vermutung, daß unter Linux 64 Bit evt. die Breite 64 Bit beträgt-> man grübelt schon drüber nach.
Ich bin halt von 32 Bit ausgegangen, daher meine Probleme.
Normalerweise programmiere ich hauptsächlich 8 Bit Mikrocontroller, und da sieht die Breite der Typen anders aus.

Es scheint ja so zu sein, daß sogar verschienen Compiler bei unterschiedlichen Betriebssystemen die Breite anders auslegen.
Und wie ich festgestellt habe, sogar zwischen 32Bit un 64Bit.
Ursprünglich wollte ich int32_t benutzen, aber ich denke mal der QT eigene Typ qint32 ist besser.

Wie macht Ihr das eigentlich ?
Benutzt Ihr char, int, long usw direkt oder nutzt Ihr auch int32_t, int16_t, qint32 oder ähnliches ?

Danke für Eure Hilfe.

Bang Johansen
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Problem mit signed long aus 4 einzelnen Bytes

Beitrag von RHBaum »

Benutzt Ihr char, int, long usw direkt oder nutzt Ihr auch int32_t, int16_t, qint32 oder ähnliches ?
Wie immer lautet die klare Eindeutige Antwort:
kommt darauf an !

Meist schreibt dir die Lib die du verwendestet eigentlich schon die Typen vor .... weil irgendwas willst ja mit den werten machen.
Arbeitest du mit Qt, isses sicher nicht verkehrt q typen zu nehmen.
Bei der Arbeit mit der STL, wo eh fast alles templetisiert ist, verhalten sich die typen eh je nach umgebung, da nimmt man gern int, size_t usw.

Musst Du doch mal Typen vorschreiben, was aber nicht zu haeufig vorkommen sollte, dann:

Soweiso typedeffen um aussagekräftige Typnamen zu bekommen !!!

Dann je nach umgebung, bist beispielsweisse von der qt abhaengig, bieten sich q typen wieder an, klar, hasst du kaum abhaengigkeiten, dann nehm ich die von der Umgebung.
also, bin ich auf win32 festgenagelt, verwend ich die __int64 / __int32 und co
bin ich auf posix unterwegs, dann int_32t und co ....

Datentypen mit fest definierter bitzahl solltest auch nur nehmen wenn du musst - aka wenn du sie binaer serialisierst.
Ansonsten sind die c++ typen die bessere wahl, weil z.b. bei int kannst dich immer drauf verlassen, das der der "schnellste" integer datentyp ist.
Wird es einmal ein system geben, was nur mit 64bit registern rechnen kann, muesst er fuer 32 bit operationen ausmaskieren -> langsam. Dort wuerde dann int niemals 32bit gross sein (falls es dann noch c++ und int im Standard standard gibt).

Ciao ....
Bang-Johansen
Beiträge: 43
Registriert: 11. Juli 2011 22:51

Re: Problem mit signed long aus 4 einzelnen Bytes

Beitrag von Bang-Johansen »

Hallo RHBaum,

Danke für die umfangreiche Antwort.

Anscheinend kann man nicht unter allen Systemen eine einheitliche Linie finden.

Aber ich kann doch davon ausgehen, wenn ich die QT internen Typen nehme,daß
dann diese Typen unter 32/64 Bit /linux/windows/Mac über gleich sind,oder ?
Dann werde ich diese auch nutzen.

Ich programmiere noch nicht sehr lange QT und C++; komme eher aus der Assembler bzw. C Ecke,
versuche aber, daß meine Programme einigermaßen sich an die Standard halten und ggf.
einigermaßen portierbar sind.

Bang-Johannsen
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Problem mit signed long aus 4 einzelnen Bytes

Beitrag von RHBaum »

diese Typen unter 32/64 Bit /linux/windows/Mac über gleich sind,oder ?
nen qint32 wird immer nen 32 bit vorzeichebehafteter integer sein, darauf kannst dich verlassen. ob aber msb oder lsb, das kann Qt auch nicht definieren. Daher ist die Frage was du unter gleich verstehst ...

Und grad wenn du aus der microcontroller ecke kommst, solltest dich von den fixen werten loesen.
daß meine Programme einigermaßen sich an die Standard halten und ggf.
einigermaßen portierbar sind.
Int, long, short bool .... sind auch standardisiert und auf allen plattformen vorhanden. Wenn es die nicht gibt, wird auf der plattform auch kein Qt laufen ^^

das deren physikalische groesse nicht fix ist, ist auch so gewollt. Da zaehlen andere Dinge, die auch was mit plattformunabhaengigkeit zu tun haben.
Stell dir vor du verwendest immer int16 statt int.
Auf 16bit prozessoren waren deine Progs richtig flott(im vergleich zu anderen).
nun compilierst auf 32 bit und peng, dein Prog wird um faktor X lahmer (im vergleich zu anderen).
Sowas sollt auch nicht passieren oder ?

Also sich auf die Datentypen fixxer Grösse zu stürzen macht nur bei binaerer serialisation sinn .... ansonsten sind die C++ Typen meist die bessere Wahl !

Ciao ....
Antworten