Forum: Compiler & IDEs char Pointer -> unsigned short (2byte) in dec.


von wissenshunger91x3 (Gast)


Lesenswert?

Hallo folgendes Problem lässt mich seit Stunden verzweifeln:

Meine Ausgangsvarriabel:
static char * biosda = (char*) 0x0400;

Die Varriabel ist 254 Bytes groß.
Bei Offset 0x00 befindet sich ein 2Byte großer Wert.
Es sollte eigentlich 0x3F8 (DEC. 1016) herrauskommen. Leider ist das 
Ergebnis immer f803.

Hier meine umwandlung:
unsigned short bitemp = (biosda [0x00]<<8) |  biosda[0x01];

Ich versteh nicht wieso die 3 immer hinter f8 steht, sie müsste davor 
stehen. Wieso klappt das nicht?

von Floh (Gast)


Lesenswert?

Schreibst du die Variable selbst rein?
Little Endian oder big endian?

von wissenshunger91x3 (Gast)


Lesenswert?

Nein, ich schreibe die Varriable nicht selbst rein. Diese liegen auf dem 
Speicher 0x0400. Und in diesem Fall auf Offset 0x00. Sprich Byte 0 und 
1.

von holger (Gast)


Lesenswert?

>unsigned short bitemp = (biosda [0x00]<<8) |  biosda[0x01];
>
>Ich versteh nicht wieso die 3 immer hinter f8 steht, sie müsste davor
>stehen. Wieso klappt das nicht?

Dann mach das doch so:

unsigned short bitemp = (biosda [0x01]<<8) |  biosda[0x00];

von wissenshunger91x3 (Gast)


Lesenswert?

Funktioniert nicht! Es ist ODER Verknüpft.

von Dirk B. (dirkb2)


Lesenswert?

wissenshunger91x3 schrieb:
> unsigned short bitemp = (biosda [0x00]<<8) |  biosda[0x01];

holger schrieb:
> unsigned short bitemp = (biosda [0x01]<<8) |  biosda[0x00];

@wissenshunger91x3
Wo ist denn da der Unterschied?

wissenshunger91x3 schrieb:
> Funktioniert nicht! Es ist ODER Verknüpft.
Super Fehlerbeschreibung. Und tolle (falsche) Begründung :-(

von wissenshunger91x3 (Gast)


Lesenswert?

Dirk B. schrieb:
> wissenshunger91x3 schrieb:
>> unsigned short bitemp = (biosda [0x00]<<8) |  biosda[0x01];
>
> holger schrieb:
>> unsigned short bitemp = (biosda [0x01]<<8) |  biosda[0x00];
>
> @wissenshunger91x3
> Wo ist denn da der Unterschied?
>
> wissenshunger91x3 schrieb:
>> Funktioniert nicht! Es ist ODER Verknüpft.
> Super Fehlerbeschreibung. Und tolle (falsche) Begründung :-(

Ich weiß zwar net genau was damit gemeind ist, aber selbst wenn ich 
beide Varriable drehe kommt das selbe Ergebnis rauß.

von holger (Gast)


Lesenswert?

>Ich weiß zwar net genau was damit gemeind ist, aber selbst wenn ich
>beide Varriable drehe kommt das selbe Ergebnis rauß.

Wie kontrollierst du das?

von wissenshunger91x3 (Gast)


Lesenswert?

Ich starte einfach den Code und somit fragt er den Speicherbereich ab.

von Dirk B. (dirkb2)


Lesenswert?

wissenshunger91x3 schrieb:
> Ich weiß zwar net genau was damit gemeind ist,
Funktioniert nicht ist die schlechteste mögliche Fehlerbeschreibung.
Und das sind beides Oder-Verknüpfungen.

wissenshunger91x3 schrieb:
> aber selbst wenn ich
> beide Varriable drehe kommt das selbe Ergebnis rauß.
Das kann nur sein wenn bei Index 0 und 1 der gleiche Wert steht.

Darum nochmal: Wie stellst du das fest?
Debuuger, printf (wenn ja, wie?), irgendetwas anderes?

von wissenshunger91x3 (Gast)


Lesenswert?

Jup, über printf.

von wissenshunger91x3 (Gast)


Lesenswert?

Also mit % d also als Decimal signed integer oder auch mit %p wie 
Pointer. Aber auch wenn ich es mit %c ausgeben, ich komme nie auf die 
Dezimal Zahl: 1016

von Floh (Gast)


Lesenswert?

Häng mal deinen Code komplett an.

von Dirk B. (dirkb2)


Lesenswert?

Du kannst nochmal zwei Sachen probieren
1
static unsigned char * biosda = (char*) 0x0400;  // oder uint8_t statt unsigned char
2
// oder/und
3
unsigned short bitemp = ((biosda [0x01] & 0xff)<<8) |  (biosda[0x00] & 0xff);

von wissenshunger91x3 (Gast)


Lesenswert?

Funktioniert leider beides nicht.  ; (

von Dirk B. (dirkb2)


Lesenswert?

Dann schreib mal was da ausgegeben wird
1
printf("00: %02x | 01: %02x\n", biosda[0x00], biosda[0x01]);

von wissenshunger91x3 (Gast)


Lesenswert?

00: f8 | 01: 03

von Helmut L. (helmi1)


Lesenswert?

wissenshunger91x3 schrieb:
> Hier meine umwandlung:
> unsigned short bitemp = (biosda [0x00]<<8) |  biosda[0x01];

Die wird auch nicht funktionieren. Du must erst deine beiden Teile nach 
unsigned short casten.

Also so:

 unsigned short bitemp = ((unsigned short)biosda [0x00]<<8) |  (unsigned 
short)biosda[0x01];

Sonst führt der Compiler die verorderung auf 8 bit char aus.

von Dirk B. (dirkb2)


Lesenswert?

Und was gibt
1
unsigned short bitemp = ((biosda[0x01] & 0xff)<<8) |  (biosda[0x00] & 0xff);
2
printf("0000: %04x\n", bitemp );

von wissenshunger91x3 (Gast)


Lesenswert?

Dirk B. schrieb:
> Und was gibtunsigned short bitemp = ((biosda[0x01] & 0xff)<<8) |
> (biosda[0x00] & 0xff);
> printf("0000: %04x\n", bitemp );

F803

von wissenshunger91x3 (Gast)


Lesenswert?

Helmut Lenzen schrieb:
> wissenshunger91x3 schrieb:
>> Hier meine umwandlung:
>> unsigned short bitemp = (biosda [0x00]<<8) |  biosda[0x01];
>
> Die wird auch nicht funktionieren. Du must erst deine beiden Teile nach
> unsigned short casten.
>
> Also so:
>
>  unsigned short bitemp = ((unsigned short)biosda [0x00]<<8) |  (unsigned
> short)biosda[0x01];
>
> Sonst führt der Compiler die verorderung auf 8 bit char aus.


Hilft leider nicht. Kommt zum selben Ergebnis f803.

von holger (Gast)


Lesenswert?

>Hilft leider nicht. Kommt zum selben Ergebnis f803.

Kann nicht sein. Zum letzten mal: Zeig dein Programm.

von wissenshunger91x3 (Gast)


Lesenswert?

Das was ich im ersten Post geschrieben habe ist eig. das Programm. Nur 
die Ausgabe fehlt.

von holger (Gast)


Lesenswert?

>Das was ich im ersten Post geschrieben habe ist eig. das Programm.

Ok, reine Zeitverschwendung. Ich bin raus.

von Helmut L. (helmi1)


Lesenswert?

wissenshunger91x3 schrieb:
> Hilft leider nicht. Kommt zum selben Ergebnis f803.

Dann vertausch die beiden Variablen mal

von wissenshunger91x3 (Gast)


Lesenswert?

Dirk B. schrieb in Beitrag #3473589:
> Dann schreib mal was da ausgegeben wirdprintf("00: %02x | 01: %02x\n",
> biosda[0x00], biosda[0x01]);

Sehr unfreundlich holger!

Dirk B. Schrieb ich ja schon beide ausgangsvarriable und auch die 
Ergebnisse die Angezeigt werden.

von wissenshunger91x3 (Gast)


Lesenswert?

Helmut Lenzen schrieb:
> wissenshunger91x3 schrieb:
>> Hilft leider nicht. Kommt zum selben Ergebnis f803.
>
> Dann vertausch die beiden Variablen mal


Wie soll ich sie tauschen?

von Helmut L. (helmi1)


Lesenswert?

Index 01 mit Index 00

von wissenshunger91x3 (Gast)


Lesenswert?

Die Bytes liegen auf einem geschützten Teil der Bios Data Area. Ich kann 
sich nicht einfach so tauschen.

von Dirk B. (dirkb2)


Lesenswert?

Dirk B. schrieb:
> Dann schreib mal was da ausgegeben wirdprintf("00: %02x | 01: %02x\n",
> biosda[0x00], biosda[0x01]);

wissenshunger91x3 schrieb:
> 00: f8 | 01: 03

Dirk B. schrieb:
> Und was gibtunsigned short bitemp = ((biosda[0x01] & 0xff)<<8) |
> (biosda[0x00] & 0xff);
> printf("0000: %04x\n", bitemp );

wissenshunger91x3 schrieb:
> F803

Ok dann noch die letzte Frage:

Und was gibt
1
unsigned short bitemp = ((biosda[0x00] & 0xff)<<8) | (biosda[0x01] & 0xff);
2
printf("0000: %04x\n", bitemp );

von wissenshunger91x3 (Gast)


Lesenswert?

Gibt auch f803 aus.

von Dirk B. (dirkb2)


Lesenswert?

Hast du Copy&Paste gemacht? Mit den Unterschieden in den Indizes, die in 
der Kommetarzeile nochmal gekennzeichnet sind?
1
unsigned short bitemp0 = ((biosda[0x00] & 0xff)<<8) | (biosda[0x01] & 0xff);
2
unsigned short bitemp1 = ((biosda[0x01] & 0xff)<<8) | (biosda[0x00] & 0xff);
3
//                                   ^ da                 und da ^

von wissenshunger91x3 (Gast)


Lesenswert?

Sorry, die letzte Varriante funktioniert.  Dirseidanke! Aber wieso? Kann 
man das gewussel ab abkürzen und kann ich genauso vorgehen wenn ich mehr 
als 2 Bytes auslesen muss?

Vielen dank erstmal für DEINE Hilfe!!!

von Dirk B. (dirkb2)


Lesenswert?

holger schrieb im Beitrag #3473312 vor 4 Stunden
> Dann mach das doch so:
>
> unsigned short bitemp = (biosda [0x01]<<8) |  biosda[0x00];

von wissenshunger91x3 (Gast)


Lesenswert?

Dirk B. schrieb:
> holger schrieb im Beitrag #3473312 vor 4 Stunden
>> Dann mach das doch so:
>>
>> unsigned short bitemp = (biosda [0x01]<<8) |  biosda[0x00];

Damit hatte ich angefang! Das funktionierte aber NICHT. Erst mit &0xFF 
hat es funktioniert.

von wissenshunger91x3 (Gast)


Lesenswert?

Ich habe jetzt dort stehen:
unsigned short bitemp = ((biosda [0x00])&0xFF) | (biosda 
[0x01]&0xFF)<<8)

Und NUR DAS funzt!

von wissenshunger91x3 (Gast)


Lesenswert?

Aber wieso?

von holger (Gast)


Lesenswert?

Aus deinem ersten Post:

unsigned short bitemp = (biosda [0x00]<<8) |  biosda[0x01];

Ergibt laut deiner Aussage 0xF803.

>Und NUR DAS funzt!

Warum hat das da oben funktioniert? Nur halt mit der falschen
Bytereihenfolge.

>Aber wieso?

Das wird irgendwie an DIR liegen.

von wissenshunger91x3 (Gast)


Lesenswert?

Nicht zu vergessen ist das &0xFF ! Erst damit gehts. Nehm ich beides weg 
gehts nicht mehr. Liegt vll. am Compiler.

von wissenshunger91x3 (Gast)


Lesenswert?

Außerdem gehts die ganze Zeit schon!! Nur die Byte reihenfolge stimmt 
nicht also statt f803 sollte eigentlich immer 3f8 raußkommen!

von Rolf Magnus (Gast)


Lesenswert?

Also wenn du die Reihenfolge tauschst, aber das &0xFF weglässt, sind die 
beiden Bytes immer noch falsch rum und erst durch das &0xFF drehen sie 
sich? Das ist allerdings sehr merkwürdig.

von wissenshunger91x3 (Gast)


Lesenswert?

Erst durch 0xFF und jetzt wäre natürlich interessant wieso.

von Dirk B. (dirkb2)


Lesenswert?

Die Berechnung erfolgt als int.
Die Werte aus biosda werden also  von (signed) char auf int erweiter.

0xf8 als char) ist aber ein negativer Wert. Darum wird der auf 0xfff8 
oder 0xfffffff8 (je nach Bitbreite vom int) erweitert.

Die 0x03 bleibt so wie sie ist.

Du hast also (0x03 <<8) | 0xfff8 = fffb

Beim Ablegen als unsigned short werden dann wieder nur diu untersten 16 
Bit genommen.

von wissenshunger91x3 (Gast)


Lesenswert?

Dirk B. schrieb:
> Die Berechnung erfolgt als int.
> Die Werte aus biosda werden also  von (signed) char auf int erweiter.
>
> 0xf8 als char) ist aber ein negativer Wert. Darum wird der auf 0xfff8
> oder 0xfffffff8 (je nach Bitbreite vom int) erweitert.
>
> Die 0x03 bleibt so wie sie ist.
>
> Du hast also (0x03 <<8) | 0xfff8 = fffb
>
> Beim Ablegen als unsigned short werden dann wieder nur diu untersten 16
> Bit genommen.

Könntest du mir das noch etwas zerkleinern mit Ergebnise um es richtig 
zu verstehen?

von Karl H. (kbuchegg)


Lesenswert?

Der springende Punkt ist, dass in C IMMER im größten Datentyp der an der 
Operation beteiligten Operanden gerechnet wird, aber nicht kleiner als 
int.

D.h. selbst wenn deine Variable ein signed char ist, so wird die 
Operation

  variable << 8

als eine int Operation ausgeführt. D.h. die 'variable' wird zunächst auf 
einen int erweitert.

Da du aber dummerweise ein
1
static char * biosda = (char*) 0x0400;
gemacht hast, hast du es hier mit einem 'char' zu tun. Ob dieser char 
nun ein 'signed char' ist oder ein 'unsigned char', dass wissen nur die 
Compilerbauer bzw. die Doku zu deinem Compiler.

So etwas macht man nicht!
Man verwendet nicht einfach nur einen 'char', wenn es wichtig ist, ob 
dieser char ein Vorzeichen hat oder nicht. Denn das macht einen 
Unterschied, wenn aus diesem char ein int geformt wird. In dem einen 
Fall findet eine Vorzeichenerweiterung statt (und aus 0xF8 wird dann im 
Falle eines 16 Bit int ein 0xFFF8) und im anderen Fall findet die nicht 
statt (und aus einem 0xF8 wird ein 16-Bit 0x00F8).
In deinem Fall ist aber dieser Uterschied entscheidend. Denn du willst 
in den oberen 8 Bit kein implizites FF stehen haben! Da muss nach wie 
vor ein 00 drinnen sein, damit du dann die 0x03 einodern kannst.

Also: gewöhn dich daran. Es gibt 3(!) verschiedene Char-Typen
1
signed char      ein "kleiner" Integer mit Vorzeichen
2
unsigned char    ein "kleiner" INteger ohne Vorzeichen
3
char             für alles was mit Textverarbeitung zu tun hat

Hast du Textverarbeitung?
Nein, hast du nicht. Also ist 'char' der falsche Datentyp. Wenn du es 
mit Bytes zu tun hast, dann verwendest du IMMER 'unsigned char'. Tust du 
es, dann hast du weniger Probleme.
1
static unsigned char * biosda = (char*) 0x0400;
2
3
// wegen little Endian liegt das Low-Byte zuerst im Speicher
4
unsigned short data = ( biosda[1] << 8 ) | biosda[0];

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

Karl Heinz schrieb:
> Wenn du es mit Bytes zu tun hast, dann verwendest du IMMER 'unsigned
> char'. Tust du es, dann hast du weniger Probleme.

Richtig. Oder halt gleich uint8_t verwenden, was auf den meisten 
Systemen auf unsigned char hinauslaufen dürfte.

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.