Hallo, ich habe eine kurze Anfängerfrage: Ich muss ein unsigned short array mit bis zu maximal 100 Wörtern, an eine Funktion übergeben die anscheinend ein unsigned char-array als Eingangswert benötigt (laut Fehlermeldung des Compilers). Konkret ist es eine Uart-Sende-Routine von meinem BlackFin. Nun meine Frage kann ich das irgendwie geschickt casten? Mein alternativer Ansatz wäre : mit Bitoperatoren, Shiften und einer Schleife das short-array erst in ein char-array zu kopieren und dieses dann an die Uart-Routine zu übergeben. Aber vllt kennt ja jemand von euch einen simpleren Ansatz. Vielen Dank im Voraus! Gruß
Welche Parameter braucht denn die Senderoutine genau? Wenn sie keine Länge als Parameter hat, dann geht es nicht. Dann kann sie nur Strings senden und dann scheitert sie an der ersten \0 die vermutlich in deinen Shorts enthalten ist.
Sry hatte ich vergessen, ja das ist korrekt. Zusätzlich zu dem char-array bekommt die Routine die Anzahl der zu sendenden Bytes. Ich habe einfach die Anzahl der Wörter mit 2 multipliziert, das sollte ja die Anzahl an Bytes sein. Hier mal der Rohbau der Senderoutine:
1 | void RS232_OutData(unsigned char *String, unsigned int anzahl){ |
2 | int i; |
3 | for (i = 0; i<anzahl;i++){ |
4 | RS232_OutChar(String[i]); |
5 | }
|
6 | }
|
dann kannst du einfach casten.
1 | unsigned short Daten[100]; |
2 | RS232_OutData( (unsigned char *)Daten, sizeof( Daten ) ); |
Peter II schrieb: > dann kannst du einfach casten. > unsigned short Daten[100]; > RS232_OutData( (unsigned char *)Daten, sizeof( Daten ) ); Wäre es dann nicht so dass es einen Array-Überlauf gibt?
1 | RS232_OutData( (unsigned char *)Daten, sizeof( Daten ) / 2 ); |
Wäre meiner Meinung nach richtiger oder? Gruß Diek
Diek schrieb: > Wäre es dann nicht so dass es einen Array-Überlauf gibt?RS232_OutData( > (unsigned char *)Daten, sizeof( Daten ) / 2 );Wäre meiner Meinung nach > richtiger oder? Oder noch besser so:
1 | RS232_OutData( |
2 | > (unsigned char *)Daten, sizeof( Daten ) / sizeof(Daten[0]) ); |
Diek schrieb: > Peter II schrieb: >> dann kannst du einfach casten. >> unsigned short Daten[100]; >> RS232_OutData( (unsigned char *)Daten, sizeof( Daten ) ); > > Wäre es dann nicht so dass es einen Array-Überlauf gibt?RS232_OutData( > (unsigned char *)Daten, sizeof( Daten ) / 2 );Wäre meiner Meinung nach > richtiger oder? > > Gruß Diek Nein das ist falsch. Die Anzahl gibt ja an wie viele unsigned char gesendet werden sollen. Aus 100 shorts werden 200 chars.
> RS232_OutData((unsigned char *)Daten, sizeof( Daten ) / sizeof(Daten[0]) );
RS232_OutData((unsigned char *)Daten, sizeof( Daten ) * sizeof(Daten[0])
);
Google mal nach "sizeof operator" Der gibt schon die Größe in Bytes zurück, egal was für ein Datentyp.
Ulrich F. schrieb: >> RS232_OutData((unsigned char *)Daten, sizeof( Daten ) / > sizeof(Daten[0]) ); > RS232_OutData((unsigned char *)Daten, sizeof( Daten ) * sizeof(Daten[0]) > ); Nein auch nicht. So wäre es am "richtigsten":
1 | RS232_OutData( (unsigned char *)Daten, sizeof(Daten) / sizeof(unsigned char) ); |
Aber der C Standard garantiert sizeof(unsigned char) = 1, also kann man sich das sparen.
:
Bearbeitet durch User
Sebastian V. schrieb: > So wäre es am "richtigsten": Warum? unsigned short Daten[100]; sizeof(Daten) liefert 100 100 / 1 sind keine 200
Ulrich F. schrieb: > sizeof(Daten) liefert 100 > 100 / 1 sind keine 200 Compiler kaputt oder deine shorts sind nur 1 Byte? Mein Compiler sagt sizeof(Daten) = 200.
Ulrich F. schrieb: > Sebastian V. schrieb: >> So wäre es am "richtigsten": > Warum? > unsigned short Daten[100]; > > > sizeof(Daten) liefert 100 Nope. sizeof liefert die Größe in Bytes. Wenn ein unsigned short 2 Bytes gross ist, dann liefert sizeof(Daten) 200.
Trundle Trollkönig schrieb: > Ich > habe einfach die Anzahl der Wörter mit 2 multipliziert Nimm nicht 2, sondern sizeof(unsigned short) anstelle der 2. Oder noch besser:
1 | anzahlBytes = sizeof(*Daten) * anzahlElemente; |
wenn der "Füllgrad" des Arrays variabel ist. Auf die Art hast du die Größe nur vom Array abhängig gemacht und musst nicht 2 'Informationen' im Einklang halten.
:
Bearbeitet durch User
Also ich würde bei dem ersten Vorschlag bleiben: Peter II schrieb: > dann kannst du einfach casten. > unsigned short Daten[100]; > RS232_OutData( (unsigned char *)Daten, sizeof( Daten ) ); Passt doch und gefällt mir besser als: RS232_OutData( (unsigned char *)Daten, 100*sizeof(unsigned short) ); <edit> solange der "Füllgrad" nicht variabel ist...
:
Bearbeitet durch User
Volker S. schrieb: > Also ich würde bei dem ersten Vorschlag bleiben: > > Peter II schrieb: >> dann kannst du einfach casten. >> unsigned short Daten[100]; >> RS232_OutData( (unsigned char *)Daten, sizeof( Daten ) ); > > Passt doch und gefällt mir besser als: > RS232_OutData( (unsigned char *)Daten, 100*sizeof(unsigned short) ); > > <edit> solange der "Füllgrad" nicht variabel ist... Das ist noch schlimmer, als den Datentyp direkt im sizeof zu verwenden. Jetzt hast du die Korrektheit des Aufrufs komplett von der Deklaration abhängig gemacht. Wann immer sich die Deklaration ändert, darfst du nicht vergessen, den Aufruf anzupassen. Der springende Punkt ist: schreibst du
1 | unsigned char Daten[100]; |
2 | |
3 | ...
|
4 | |
5 | RS232_OutData( (unsigned char *)Daten, sizeof(Daten) ); |
dann passt dir der Compiler die Byteangabe an. Und zwar macht der das immer korrekt (solange Daten in Arrayform sichtbar ist). Und genau das willst du haben: du willst, dass dir der Compiler die Dinge anpasst, die er anpassen kann und du willst dich als Programmierer davon entlasten. Die Praxis zeigt nämlich auch, warum man das will.
:
Bearbeitet durch User
>void RS232_OutData(unsigned char *String, unsigned int anzahl){
Aus diesen Grund haben meine Senderoutinen gewöhnlich einen
void-Pointer. Damit castest du einfach in der RS232_OutData-Routine auf
das was Du intern brauchst. Und ausserhalb kann alles mitgegeben werden.
1 | void RS232_OutData(void *data, unsigned int length ) |
2 | {
|
3 | int i = 0; |
4 | unsigned char *String = data; |
5 | while ( i < length ) |
6 | {
|
7 | RS232_OutChar( String[i++] ); |
8 | }
|
9 | }
|
Matthias L. schrieb: >>void RS232_OutData(unsigned char *String, unsigned int anzahl){ > > Aus diesen Grund haben meine Senderoutinen gewöhnlich einen > void-Pointer. Yep. Und abgesehen davon, ist die Bezeichnung das Arguments mit 'String' grob irreführend. Das ist kein String, das sind einfach nur Bytes.
Karl H. schrieb: > Das ist noch schlimmer, als den Datentyp direkt im sizeof zu verwenden. > Jetzt hast du die Korrektheit des Aufrufs komplett von der Deklaration > abhängig gemacht. Wann immer sich die Deklaration ändert, darfst du > nicht vergessen, den Aufruf anzupassen. Ähhhh, das war eigentlich so, dass ich deinen eigenen Vorschlag so gedeutet habe, als wolltest du es genau so "schlimm" anwenden, bevor du die Ergänzungen mit dem "Füllstand" gemacht hast...
Volker S. schrieb: > Karl H. schrieb: >> Das ist noch schlimmer, als den Datentyp direkt im sizeof zu verwenden. >> Jetzt hast du die Korrektheit des Aufrufs komplett von der Deklaration >> abhängig gemacht. Wann immer sich die Deklaration ändert, darfst du >> nicht vergessen, den Aufruf anzupassen. > > Ähhhh, das war eigentlich so, dass ich deinen eigenen Vorschlag so > gedeutet habe, als wolltest du es genau so "schlimm" anwenden, bevor du > die Ergänzungen mit dem "Füllstand" gemacht hast... Ausgangspunkt war eigentlich, dass er die 2 direkt im Code hat. Das ist die schlimmste aller Varianten.
Karl H. schrieb: > Matthias L. schrieb: >>>void RS232_OutData(unsigned char *String, unsigned int anzahl){ >> >> Aus diesen Grund haben meine Senderoutinen gewöhnlich einen >> void-Pointer. > > Yep. > Und abgesehen davon, ist die Bezeichnung das Arguments mit 'String' grob > irreführend. Das ist kein String, das sind einfach nur Bytes. Seh ich nicht so. void* ist ja im Grunde "Pointer auf weiß ich nicht". Aber der Typ ist ja bekannt, nämlich (mehrere) Bytes. Um das Problem mit dem String (wegen char) zu umgehen, fände ich das unten richtiger. Ist zwar intern das Gleiche, aber die Intention ist besser erkennbar.
1 | #include <stdint.h> |
2 | void RS232_OutData(uint8_t *data, unsigned int anzahl); |
Karl H. schrieb: > Ausgangspunkt war eigentlich, dass er die 2 direkt im Code hat. > Das ist die schlimmste aller Varianten. Na ja, die 2 war sowieso indiskutabel;-)I Volker S. schrieb: > Google mal nach "sizeof operator" > Der gibt schon die Größe in Bytes zurück, egal was für ein Datentyp.
test schrieb: > Seh ich nicht so. > void* ist ja im Grunde "Pointer auf weiß ich nicht". Aber der Typ ist ja > bekannt, nämlich (mehrere) Bytes. Um das Problem mit dem String (wegen > char) zu umgehen, fände ich das unten richtiger. Ist zwar intern das > Gleiche, aber die Intention ist besser erkennbar. Datei-Funktionen (read, write) verwenden auch void*. Daran würde ich mir auch orientieren. Dann kann der cast immer wegfallen. Im Computer sind Daten immer ein Array von Byte.
test schrieb: > Seh ich nicht so. > void* ist ja im Grunde "Pointer auf weiß ich nicht". Eben. 'String' hat ja in C eine feststehende Bedeutung. Das ist eine Abfolge von Bytes, die mit einem 0 Byte endet. > char) zu umgehen, fände ich das unten richtiger. Ist zwar intern das > Gleiche, aber die Intention ist besser erkennbar. > >
1 | #include <stdint.h> |
2 | > void RS232_OutData(uint8_t *data, unsigned int anzahl); |
den void* finde ich schon ok. Aber so wie du würde ich das Argument 'data' oder 'bytes' nennen und nicht 'String'. Denn das ist kein String im C-Sinne. Und nein, das Argument, dass es dann ja wohl keine 'anzahl' geben würde, kann ich so auch nicht akzeptieren. Die strn* Funktionen nehmen auch eine Anzahl und behandeln einen String trotzdem als C-String. Den void* würde ich trotzdem nehmen, weil er mir das ständige Casten beim Aufruf erspart. Davon hab ich nichts, wenn ich Argumente beim Aufruf dauern zurecht casten muss, es sein denn ich hab als Aufrufer zufällig uint8_t. Gerade bei derartigen Funktionen ist ein void* praktisch immer das Kennzeichen, dass man es mit rohen Bytes zu tun hat. Siehe zb den Unterschied zwischen den mem*() Funktionen und den str*() Funktionen. Die mem* Funktionen haben allesamt einen void*.
:
Bearbeitet durch User
Eine Funktion, die auf Strings steht erwartet etwas wie: '1', ' ', 'V', 'e', 'r', 's', 'u', 'c', 'h', '\0'. Eine Funktion, die auf Arrays steht erwartet etwas wie: '1', ' ', 'V', 'e', 'r', 's', 'u', 'c', 'h', '?', '?' mit Länge. Hinter dem Array kann noch Rest vom letzten Mal stehen. Ein short Array, gefüllt mit Zeichen sieht aber folgendermaßen aus: '1', 0; ' ', 0; 'V', 0; 'e', 0; 'r', 0; 's', 0; 'u', 0; 'c', 0; 'h', 0; '?', 0; '?', 0 mit Länge. Anstelle der Nullen kann auch irgendein Schmutz vorkommen. Also geht nur Funktion umschreiben oder vor der Übergabe Array umkopieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.