char Pointer -> unsigned short (2byte) in dec.

Gast #3473185
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?
Gast #3473312
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];
Gast #3473390
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ß.
#3473438
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?
Gast #3473641
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.
Gast #3473695
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.
#3473720
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 );
#3473734
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 ^
Gast #3473746
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!!!
Gast #3473789
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.
#3473931
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.
Gast #3474715
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?
#3475935
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];

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren