Forum: Mikrocontroller und Digitale Elektronik Cast short zu char!


von Trundle Trollkönig (Gast)


Lesenswert?

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ß

von Peter II (Gast)


Lesenswert?

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.

von Trundle Trollkönig (Gast)


Lesenswert?

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
}

von Peter II (Gast)


Lesenswert?

dann kannst du einfach casten.
1
unsigned short Daten[100];
2
RS232_OutData( (unsigned char *)Daten, sizeof( Daten ) );

von Diek (Gast)


Lesenswert?

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

von Diek (Gast)


Lesenswert?

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]) );

von Sebastian V. (sebi_s)


Lesenswert?

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.

von Ulrich F. (Gast)


Lesenswert?

> RS232_OutData((unsigned char *)Daten, sizeof( Daten ) / sizeof(Daten[0]) );
RS232_OutData((unsigned char *)Daten, sizeof( Daten ) * sizeof(Daten[0]) 
);

von Volker S. (vloki)


Lesenswert?

Google mal nach "sizeof operator"
Der gibt schon die Größe in Bytes zurück, egal was für ein Datentyp.

von Sebastian V. (sebi_s)


Lesenswert?

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
von Ulrich F. (Gast)


Lesenswert?

Sebastian V. schrieb:
> So wäre es am "richtigsten":
Warum?
unsigned short Daten[100];


sizeof(Daten) liefert 100
100 / 1 sind keine 200

von Sebastian V. (sebi_s)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
von Ulrich F. (Gast)


Lesenswert?

Karl H. schrieb:
> sizeof liefert die Größe in Bytes.
YES!
(du recht)

von Volker S. (vloki)


Lesenswert?

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
von Diek (Gast)


Lesenswert?

Dann würde da aber stehen:

RS232_OutData( (unsigned char *)Daten, 200 );

von Karl H. (kbuchegg)


Lesenswert?

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
von Matthias L. (Gast)


Lesenswert?

>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
}

von Karl H. (kbuchegg)


Lesenswert?

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.

von Volker S. (vloki)


Lesenswert?

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...

von Karl H. (kbuchegg)


Lesenswert?

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.

von test (Gast)


Lesenswert?

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);

von Volker S. (vloki)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
von Amateur (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.