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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Schreibst du die Variable selbst rein?
Little Endian oder big endian?

von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Funktioniert nicht! Es ist ODER Verknüpft.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Ich starte einfach den Code und somit fragt er den Speicherbereich ab.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Jup, über printf.

von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Häng mal deinen Code komplett an.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Funktioniert leider beides nicht.  ; (

von Dirk B. (dirkb2)


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

von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
00: f8 | 01: 03

von Helmut L. (helmi1)


Bewertung
0 lesenswert
nicht 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)


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

von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
>Hilft leider nicht. Kommt zum selben Ergebnis f803.

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

von wissenshunger91x3 (Gast)


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

von holger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
>Das was ich im ersten Post geschrieben habe ist eig. das Programm.

Ok, reine Zeitverschwendung. Ich bin raus.

von Helmut L. (helmi1)


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

Dann vertausch die beiden Variablen mal

von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Index 01 mit Index 00

von wissenshunger91x3 (Gast)


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

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Gibt auch f803 aus.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

Und NUR DAS funzt!

von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Aber wieso?

von holger (Gast)


Bewertung
0 lesenswert
nicht 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)


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

von wissenshunger91x3 (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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) (Moderator)


Bewertung
0 lesenswert
nicht 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 Moderator
von Mark B. (markbrandis)


Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.