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