Byte !?

Hallo,

Ich hab ein Problem mit den Datentypen in vc++, undzwar:

Was genau ist ein ascii!
Was genau ist ein byte!
Was genau ist ein unsigned char!

Ich komme nicht einfach so auf diese Fragen, undzwar wollte ich
eine Typenumwandlung machen von char in BYTE und dafür wären diese Infos glaube ich hilfreich!
Ich glaube ich muss mein „char“ in „unsigned char“ wandeln,
wenn mich nicht alles täuscht wird dann daraus eine Zahlenfolge von einsen und nullen, und ein BYTE sind ja 8 Bit -> hmm… fertig?!

Ich bin für jede Hilfe dankbar…

MfG

Hallo,

Ich hab ein Problem mit den Datentypen in vc++, undzwar:

Was genau ist ein ascii!

American Standard Code for Information Interchange. Kein Datentyp.

Was genau ist ein byte!

Zusammenfassung von 8 Bit, auch „Oktett“ genannt.

Was genau ist ein unsigned char!

Ah, jetzt kommen wir in den interessanteren Bereich. Ein „char“ ist im „ascii“ code genau ein „signed byte“ groß. Die Amerikaner haben nämlich keinen Bedarf an vielen Sonderzeichen und kommen daher mit 7 Bit (0…127) aus. Das 8. bit wird dann für das Vorzeichen verwendet (-128…0). Du solltest Dir mal ein Kapitel über Datentypen in einem beliebigen C-Buch durchlesen. Auch solche Stichworte wie „Zweierkomplement“ und BCD wären gut zu kennen. Du kannst ja mal ein wenig googeln.

unsigned char ist ein Byte ohne Vorzeichen, d.h. Dir stehen die Werte von 0…255 zur Verfügung. Es ist wohl das, was Du normalerweise unter einem Byte verstehst.

8 Bit haben aber beide Werte! Ein Char ist mithin immer ein Byte groß, egal ob signed oder unsigned. Es geht dabei nur um die Interpretation der einzelnen Bits.

Gruß

Fritze

hallo.

also du liegst richtig damit, dass du im prinzip char in unsigned char umwandeln mußt. laut microsoft dokumentation ist BYTE ein unsigned char („typedef unsigned char BYTE;“).

gruss tobias

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

hmm…

alles klar, kapiere ich!
Alles Interpretationssache der bits!

d.h. also, wenn ich vorhabe ein char in ein byte umzuwandeln brauch in nur:

char c=‚a‘;
BYTE b=(unsigned char)c;

zu schreiben!?

das würde praktisch a -> 00110111 (ausm kopf!!)
machen, hab ich recht?

Hallo,

keine Ahnung wo Du diese „BYTE“ herhast. ISO-konform ist es meines Wissens nicht. Ein char ist genau ein byte groß. Du musst da nichts casten. Ein „a“ ist immer „01100001“ (oder „0x61“ oder „97“).

Wenn Du bei einer Ausgabe (z.b. über printf) diesen char als Zeichen interpretierst, bekommst Du ein „a“. Als Dezimalzahl ausgegeben bekommst Du 97. Erst bei Werten >127 wird es interessant. Du bekommst negative Dezimalzahlen oder besondere nationale Sonderzeichen, je nach eingestellter Codepage. Daher gibt es den „unsigned char“, der Dir die Zahlen von 128-255 liefert.

Die binäre Darstellung „10100111“ bedeutet also:

Den Buchstaben „ö“ als Buchstabe interpretiert
Die Zahl -89 als char
Die Zahl 167 als unsigned char.

Es sind immer die selben 8 Bit und sie belegen in Deinem Speicher genau ein Byte. Der Datentyp „byte“ ist komplett überflüssig.

Gruß

Fritze

hmm…

ok… ich werd mal jetzt bissl praktisch!
ich hab hier eine Funktion, die Daten über die serielle Schnittstelle schickt:

Port.Write(BYTE* Buffer, // data buffer
LONG Count // number of bytes to write
);

Und ich will sozusagen ein String rüberschicken, sprich:
char s[]=„Halloooo“;

Dies ist mein Problem!
Wüsstest du hierzu die Lösung?

Ich dachte mir, ich wandle jedes char in unsigned char[]!
In ner for schleife kein Problem!
Und jetzt stellt sich die Frage,
wie pack ich das in bytes bzw byte* !?

danke dass du mir hilfst!

Hallo,

meines wissens nach, musst du nix casten.
Das hieße:

char s[]="Halloooo";
Port.Write(s, strlen(s));

MfG
DDR-RAM

etwas fehlt da natürlich ^^
richtig muss es:

char s[]="Halloooo";
Write((BYTE\*)s, strlen(s));

MfG
DDR-RAM

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

hmm…

ok… ich werd mal jetzt bissl praktisch!
ich hab hier eine Funktion, die Daten über die serielle
Schnittstelle schickt:

Port.Write(BYTE* Buffer, // data buffer
LONG Count // number of bytes to write
);

Und ich will sozusagen ein String rüberschicken, sprich:
char s[]=„Halloooo“;

Dies ist mein Problem!
Wüsstest du hierzu die Lösung?

Ich dachte mir, ich wandle jedes char in unsigned char[]!
In ner for schleife kein Problem!
Und jetzt stellt sich die Frage,
wie pack ich das in bytes bzw byte* !?

Um die Vorgehensweise zu verdeutlichen, greife ich noch einmal
etwas weiter aus. Am Anfang stand die Frage, was ein BYTE bzw
was ein char oder unsigned char ist.
Die kleinste Einheit eines Rechners ist das Bit und kann die
Zustände 0 und 1 annehmen. Da das nicht gerade viele Informationen
sind,hat man sich entschossen 8 Bit zu einem Byte zusammen zu fassen.
Ein Byte sind also immer 8 Bit und ein Byte ist überlicherweise
die kleinste addressierbare Einheit im Rechner. (es gibt Ausnahmen,
die sind für sich aber nicht praxisrelevant).

Nun stellt sich die Frage, wie ein Byte zu interpretieren ist. Ein
unsigned char betrachtet die 8 Bits als eine vorzeichenlose Zahl,
ein signed char als eine Zahl mit Vorzeichen. Dem entsprechend kannst
du entweder die Zahlen von -128 bis 127 oder von 0 bis 255 darstellen.
Ähnlich sieht das bei den Typen long oder int aus. Hier verwendet man
mehrere Bytes, unter Windows fassen beide Typen jeweils 4 Bytes und
sind somit 32-Bit groß. Die größere hängt aber vom Betriebssystem ab,
unter Linux oder kann kann ein long auch 64Bit haben oder ein int nur
16 bit. Du kannst aber sicher sein, der char hat immer 8 Bits.

Beim char kommt als Besonderheit noch hinzu, dass es eigentlich drei
Typen sind: „char“, „signed char“ und „unsigned char“. Beim „char“
war man sicht nicht sicher, somit kann ein „char“ auf dem einen
System ein Vorzeichen besitzen und auf dem anderen System keines. Wenn du
wirklich sicher sein willst, verwendest du stattdessen „signed char“
oder „unsigned char“. (bei allen anderen Typen steht in Gedanken ein signed
davor, es gibt als nur den „(signed) int“ und den „unsigned int“)

Den Typen BYTE kennst C/C++ gar nicht, aber du kannst ihn durch einen alias
bekannt machen: „typedef unsigned char BYTE;“ Überall wo du nun BYTE
verwendest, setzt der Compiler ein „unsigned char“ ein.

Jetzt wird es interessant. Du hast folgende Funktion:

void kopiere(BYTE* _bytes, long _anzahl);

Mit dem Wissen von oben, weisst du, die Funktion heisst eigentlich

void kopiere(unsigned char* _bytes, long _anzahl);

char puffer[5];

Diese Anweisung legt dir einen Puffer von 5 Zeichen an. Du weisst, dass
„char“ und „unsigned char“ die gleiche Größe haben (s.o.), zum Kopieren
stört es nicht weiter, wenn die Inhalte unterschiedlich interpretiert
werden können. Demnach kannst du die Funktion wie folgt verwenden:

kopiere( puffer, sizeof(puffer) );

oder

kopiere( & puffer[0], sizeof(puffer) );

Der Compiler nimmt automatisch eine Typeumwandlung vor, voll
ausgeschrieben hätte nun da gestanden:

kopiere( (unsigned char*)& puffer[0], sizeof(puffer) );

In Worten: du hast einen Zeiger, der auf eine Sequenz von „char“
zeigt. Durch den cast (so heist die Umwandluung) sagst du,
interpertiere diesen Zeiger als einen Zeiger auf ein „unsigned char“.

Nun fragst du dich sicherlich, warum ich dir all diese Details
beschrieben habe. BYTE, „char“, „signed char“ und „unsigned char“
haben doch alle dieselbe Größe. Warum also das ganze casten?

Stellt dir dazu mal folgende Ausgangsitutaion vor:

int puffer[5];

Dem C Compiler kannst du oft auch so etwas unterschieben:

kopiere( (BYTE*)puffer, sizeof(puffer));

Eine böse Falle!!! => Du hast eine Sequenz von 5 int, ein int
umfasst abermehr BYTEs als ein char. „puffer“ ist in diesem
Fall der Zeiger auf den ersten int, durch den cast sagst du
„interpretiere den Inhalt, auf den ich Zeige, als einen char“

Da int[5] größer ist als char[5] kopiert du nur den Anfang von
den 5 int, nicht aber den genauen Wert.

Mir war es wichtig, das mal anzureissen!

Gruß Markus

1 Like

Markus, ich bin platt!

Extrem krass genialen Dank an dich!
Ich werd das ganze erstmal inhalieren!

MfG

noch ne Frage zu diesem Themenbereich!
Erstmal danke an Euch alle, dass Ihr mir weitergeholfen habt!

ich hab mir mit den ganzen Infos, die ich jetzt habe bissl was zusammengebastelt!
Es funktioniert aber irgendwie nicht!
Der Grund dafür ist glaube ich, dass mein Listener
am Ende jedes Satzes den ich ihm schicke ein erwartet.

Ich hab mal rumgegoogelt:

CR entspricht 13(dezimal) 0D (Hexadezimal)
und als Zeichen/Char ist es eine „musikNote“!

so!

also denke ich mir, schreibst du nachdemdu dein text über die schnittstelle gedrückt hast noch ein cf un lf nach!

Code:
/* Tut Bytes auf Schnittstelle schreiben
LONG Write(BYTE* Buffer, // data buffer
LONG Count // number of bytes to write
);
*/

char a[]=„Hallo…“;
Write((unsigned char*)a,sizeof(a));
Write((unsigned char*)13,1);//CR
Write((unsigned char*)10,1);//LF

//Resultat --> nix passiert,d.h. Listener empfängt nix!

Jetzt hätte ich noch ne Idee, undzwar ich schicke das CR und LF unmittelbar im Text mit, d.h. mein char a[] soll diese „Signale“
schon beinhalten!
Und da komm ich wieder durcheinander!

Wie soll das gehen? ich kann ja nicht „eine Musiknote“*
und „nen weisen Kreis auf schwarzen Hintergrund“* in mein char einfügen?

*Symbole für CR und LF in char (glaub ich jedenfalls)

MfG

Hallo Bacho,

Wie soll das gehen? ich kann ja nicht „eine Musiknote“*
und „nen weisen Kreis auf schwarzen Hintergrund“* in mein char
einfügen?

*Symbole für CR und LF in char (glaub ich jedenfalls)

Versuch es mal mit einem Cast eines Integers auf char:

char z\_lf = char(10) // line feed
char z\_cr = char(13) // carriage return

Gruß
Jens

Jepp…

Hab ich gemacht,

char s[]=„Hallooo…“;

Write((unsigned char*)a,sizeof(a));/*
Write((unsigned char*)13,1);
Write((unsigned char*)10,1);

Aber das geht irgendwie nicht!?
Deswegen hatte ich mir überlegt, ich versuche dieses CR und LF irgendwie
in mein char s[] einzubauen!

In etwa:
char s[]=„Halloo…[CR][LF]“; // char(13) 00001101 0x0A
irgendwie in mein String reinbastle?

MfG

CR entspricht 13(dezimal) 0D (Hexadezimal)
und als Zeichen/Char ist es eine „musikNote“!

Die Note ist Zufall, die Zeichen 0-31 sind Steuercodes
und nicht-darstellbare Zeichen. ASCII(6) löst beispielseweise einen Alarmton aus.
Merken:
0-31 nicht darstellbare Steuerzeichen
32-127 standardisiert, d.h. immer die gleichen Zeichen
128-255 Abhängig von der Codeseite, beispielweise sind hier die deutschen Umlaute ÄäÖöÜü und auch das ß untergebracht.

so!

also denke ich mir, schreibst du nachdemdu dein text über die
schnittstelle gedrückt hast noch ein cf un lf nach!

Code:
/* Tut Bytes auf Schnittstelle schreiben
LONG Write(BYTE* Buffer, // data buffer
LONG Count // number of bytes to write
);
*/

char a[]=„Hallo…“;
Write((unsigned char*)a,sizeof(a));
Write((unsigned char*)13,1);//CR
Write((unsigned char*)10,1);//LF

//Resultat --> nix passiert,d.h. Listener empfängt nix!

Hier bist du wieder in die Falle gestolpter! Mich wundert es, dass dein Programm nicht abgestürzt ist! Du gibst deiner Funktion als input eine Zahl (die 13), und sagst „interpretiere diese Zahl als einen Zeiger auf die Speicherzelle 13“. Was steht wohl in dieser Speicherzelle?

char CR = 13;
Write( (unsigned char*) &CR, 1 );

Jetzt hätte ich noch ne Idee, undzwar ich schicke das CR und
LF unmittelbar im Text mit, d.h. mein char a[] soll diese
„Signale“
schon beinhalten!
Und da komm ich wieder durcheinander!

Wie soll das gehen? ich kann ja nicht „eine Musiknote“*
und „nen weisen Kreis auf schwarzen Hintergrund“* in mein char
einfügen?

*Symbole für CR und LF in char (glaub ich jedenfalls)

Doch, die gibt es :o)

\t Tabulator
\v Zeilensprung
\r Zeilenrücklauf CR=>CARRIAGE RETURN
\n neue Zeile LF
\a Signalton
\b Backspace
\ Backslash
’ ’
" "

Beispiel:

char* mein_text = „Hallo\r\n“;

Etwas umständlicher geht es auch so

char mein_text[] = {‚H‘,‚a‘,‚l‘,‚l‘,‚o‘,’\r’,’\n’,’\0’}; // anschliessende Null

Abschliessend noch eine wichtige Randbemerkung:
Eine Reihe von Betriebssystemfunktionen erlauben dir das Öffnen von Dateien und anderen Geräten in zwei Modi, im TEXTmodus und im BINÄRmodus. Während der Binärmodus deine Daten so wie sie vorliegen wegschreibt, nimmt der Textmodus konvertierungen vor, z.B.: wird das Zeichen \n abhängig vom Betriebssystem umgewandelt, schreibst du eine Zeichenkette mit dem \n weg, so wandelt Windows sie in die Sequenz \r\n (0x0d 0x0a) um, während Linux ein \n und ein Macintosh ein \r daraus macht. Bei deiner Schnittstelle solltest du, sofern das möglich ist, den Binärmodus verwenden, sonst suchst du nach einem Fehler der gar keiner ist.

Gruß Markus

Hallo Bacho,

versuch es mal mit der string-Klasse. Mit ihr könnte man zum Beispiel wie folgt vorgehen:

#include 
using std::string;
//...
//...
char\* message = "Irgend eine Nachricht an rs232";
string str\_message( message );
str\_message.push\_back( char(13) );
message = (char\*)str\_message.c\_str();

Dies sieht zwar etwas umständlich aus, müsste jedoch funktionieren.
Ich würde an deiner Stelle eine Klasse ‚SerialPort‘ schreiben, die die Memberfunktionen ‚open‘, ‚close‘, ‚write‘ und ‚read‘ hat. Ich habe das vor erst kurzem selber gemacht (eine Klasse, die gleichzeitig für linux und WIN32 funktioniert). Wenn es dich interesiert, kann ich dir den Quellcode mal zukommen lassen.

Viele Grüße
Jens

Mannomann…
alles klar! ES FUNKT!
am ende wars:

char t[]=„Hallo…\r\n“;
Write((unsigned char*)t,sizeof(t));

Ich danke euch allen Jungs!!!
–>Marcus
–>Jens
–>Tobias
–>Fritz
–>DDR-RAM

Werd mir Mühe geben euch auch weiterhin
mit Fragen zu durchlöchern… :.p

MfG

Mannomann…
alles klar! ES FUNKT!
am ende wars:

char t[]=„Hallo…\r\n“;
Write((unsigned char*)t,sizeof(t));

Super! Noch eine kleine Anmerkung am Rande:

sizeof(t) liefert dir nur den korrekten Wert, weil t als char[] definiert ist. Folgender Ausdruck hingegen liefert dir ein anderes Ergebnis:

char* t = „Hallo…\r\n“;

sizeof(t) liefert dir die Größe eines Pointers. Im ersten Fall handelte es sich um ein Feld. Ich fand das erwähnenswert, weil es praktisch ansonsten keine Unterschiede gibt und ich früher auch darüber gestolptert bin. Sobald t zur Laufzeit berechnet wird, wirst du statt sizeof(t) strlen(t) verwenden müssen.

Ich danke euch allen Jungs!!!
–>Marcus

Markus (räusper :o)

–>Jens
–>Tobias
–>Fritz
–>DDR-RAM

Werd mir Mühe geben euch auch weiterhin
mit Fragen zu durchlöchern… :.p

Freue mich, das wir dir helfen konnten!

Gruß Markus