struct zu char array casten

Gast #1934735
Lesenswert?

Hallo,

Irgendwie stehe ich grad auf dem Schlauch.
Ich möchte mir im Prinzip über ein struct ein Protokollzusammenbauen 
welches dann über uart gesendet werden soll.
Der struct sieht wie folgt aus:
1
struct data
2
{
3
  unsigned short header;
4
  unsigned short data_a;
5
  unsigned short data_b;
6
  unsigned short data_c;
7
  unsigned short data_d;
8
  unsigned short data_e;
9
  unsigned short data_f;
10
  unsigned short data_g;
11
  unsigned short data_h;
12
  unsigned short eof;
13
};

Nun habe ich einfach das Problem das ich nicht weiß wie ich dieses 
struct am besten zu einem Char array caste um es über USART zu senden.

Ich denke ich muss es irgendwie über einen Zeiger auf die Adresse machen 
oder?

Gruß Tobias
Gast #1934835
Lesenswert?

Hab mal eben versucht das ganze in c++. Hier auf den Rechner 
nachzuvollziehen

Allerdings meckert er bei dem cast :(

Mein Code sieht momentant wie folgt aus:
1
#include "stdafx.h"
2
struct data
3
{
4
  unsigned char header;
5
  unsigned short data_a;
6
  unsigned short data_b;
7
  unsigned short data_c;
8
  unsigned short data_d;
9
  unsigned short data_e;
10
  unsigned short data_f;
11
  unsigned short data_g;
12
  unsigned short data_h;
13
  unsigned char eof;
14
};
15

16
int main(int argc, char* argv[])
17
{
18
  struct data Daten;
19
  char *p_Char;
20
  Daten.data_a=55;
21
  Daten.data_b=55;
22
  Daten.data_c=55;
23
  Daten.data_d=55;
24
  Daten.data_e=55;
25
  Daten.data_f=55;
26
  Daten.data_g=55;
27
  Daten.data_h=55;
28
  Daten.eof =';';
29
  Daten.header='h';
30
  p_Char = (char*)Daten;
31
  //printf("%s",p_Char);
32
  return 0;
33
}
Gast #1934843
Lesenswert?

Klaus Wachtler schrieb:
> TM schrieb:
>> p_Char = (char*)Daten;
>
> es müsste ja auch heißen:
> p_Char = (char*)&Daten;

Danke das wars.
Er gibt leider nur noch nicht den gesamten Frame aus sondern nur ein 
Teil.
1
#include "stdafx.h"
2
struct data
3
{
4
  unsigned char header;
5
  unsigned short data_a;
6
  unsigned short data_b;
7
  unsigned short data_c;
8
  unsigned short data_d;
9
  unsigned short data_e;
10
  unsigned short data_f;
11
  unsigned short data_g;
12
  unsigned short data_h;
13
  unsigned char eof;
14
};
15
int i;
16
int main(int argc, char* argv[])
17
{
18
  struct data Daten;
19
  char *p_Char;
20
  Daten.data_a=55;
21
  Daten.data_b=55;
22
  Daten.data_c=55;
23
  Daten.data_d=55;
24
  Daten.data_e=55;
25
  Daten.data_f=55;
26
  Daten.data_g=55;
27
  Daten.data_h=55;
28
  Daten.eof =';';
29
  Daten.header='h';
30
  p_Char =  (char*)&Daten;
31
  printf("%s",p_Char);
32
  scanf("%i",&i);
33
  return 0;
34
}
#1934860
Lesenswert?

TM schrieb:
> Er gibt leider nur noch nicht den gesamten Frame aus sondern nur ein
>
> Teil.
Naja, wie Karl-Heinz schrieb: ein Char-Array ist noch kein String.
Du hast in Deiner Struktur Chars und Short-Integer. Bei den Integern 
wird irgendwo auch ein Nullbyte dazwischen sein und dann hört die 
String-Ausgabe auf.

Was ist daran überraschend?

Grüße,
  Stefan

P.S.: auch von mir: was willst Du machen?
#1934866
Lesenswert?

Und ich werden den Verdacht nicht los, das du in Wirklichkeit gar keinen 
Cast brauchst, sondern eine ASCII Übertragung machen willst.

Daher nochmal die Frage: Was soll über die Leitung gehen?
Ganz konkret in deinem Beispiel. Wie sollen die Bytes, die über die 
Leitung gehen aussehen?
Gast #1934889
Lesenswert?

Ok super das funktinoiert soweit, das mit der hexadezimalen ausgabe 
kannte ich noch gar nicht.
Allerdings packt er mir nach jedem char das ich ins frame schreibe zwei 
hohe Werte mit dazu(also irgendwie einen nicht initialisierten 
speicherbereich oder so).

Die Ausgabe sieht wie folgt aus:

68 <-- h für header
ffffffcc
37 <-- data
00
37
00
37
00
37
00
37
00
37
00
37
00
37
00
3b <-- Simikolon
ffffffcc

Dazu nutze ich nun folgenden code:
1
#include "stdafx.h"
2
struct data
3
{
4
  unsigned char header;
5
  unsigned short data_a;
6
  unsigned short data_b;
7
  unsigned short data_c;
8
  unsigned short data_d;
9
  unsigned short data_e;
10
  unsigned short data_f;
11
  unsigned short data_g;
12
  unsigned short data_h;
13
  unsigned char eof;
14
};
15
int i;
16
int main(int argc, char* argv[])
17
{
18
  char Datapacket[18];
19
  struct data Daten;
20
  char *p_Char;
21
  Daten.data_a=55;
22
  Daten.data_b=55;
23
  Daten.data_c=55;
24
  Daten.data_d=55;
25
  Daten.data_e=55;
26
  Daten.data_f=55;
27
  Daten.data_g=55;
28
  Daten.data_h=55;
29
  Daten.eof =';';
30
  Daten.header='h';
31
  p_Char =  (char*)&Daten;
32
  for( int x = 0; x <sizeof( struct data );x++ )
33
  {
34
  printf("%02x",p_Char[x]);
35
  printf("\n");
36
  }
37
  scanf("%i",&i);
38
  return 0;
39
}
#1934904
Lesenswert?

TM schrieb:
> Ok super das funktinoiert soweit, das mit der hexadezimalen ausgabe
> kannte ich noch gar nicht.
> Allerdings packt er mir nach jedem char das ich ins frame schreibe

Dein Frame besteht aus unsigned short!
Ein unsigned short ist kein char!

> hohe Werte mit dazu(also irgendwie einen nicht initialisierten
> speicherbereich oder so).

keinesfalls. Das sind die unsigned short. Die bestehen nun mal aus 2 
Bytes.
Gast #1934914
Lesenswert?

Karl heinz Buchegger schrieb:
> TM schrieb:
>> Ok super das funktinoiert soweit, das mit der hexadezimalen ausgabe
>> kannte ich noch gar nicht.
>> Allerdings packt er mir nach jedem char das ich ins frame schreibe
>
> Dein Frame besteht aus unsigned short!
> Ein unsigned shotr ist kein char!

Ist nen bisschen blöd das ich das erste Mal mit structs arbeite ist 
alles im struct nach dem größten datentyp geregelt oder wie ?
Mein header und eof sollten doch eigentlich char sein.
#1934919
Lesenswert?

TM schrieb:
> Karl heinz Buchegger schrieb:
>> TM schrieb:
>>> Ok super das funktinoiert soweit, das mit der hexadezimalen ausgabe
>>> kannte ich noch gar nicht.
>>> Allerdings packt er mir nach jedem char das ich ins frame schreibe
>>
>> Dein Frame besteht aus unsigned short!
>> Ein unsigned shotr ist kein char!
>
> Ist nen bisschen blöd das ich das erste Mal mit structs arbeite

Das hat mit struct nicht das geringste zu tun.

Unterschiedliche Datentypen haben unterschiedliche 
Speicheranforderungen.
Und ein unsigned short braucht nun mal 2 Bytes.

> alles im struct nach dem größten datentyp geregelt oder wie ?

Nein.
Warum sollte es?

Die Byteabfolge ist doch genau so, wie du sie in der Struktur geregelt 
hast
1
struct data
2
{
3
  unsigned char header;      // 1 Byte
4
  unsigned short data_a;     // 2 Bytes
5
  unsigned short data_b;     // 2 Bytes  
6
  unsigned short data_c;     // 2 Bytes
7
  unsigned short data_d;     // 2 Bytes
8
  unsigned short data_e;     // 2 Bytes
9
  unsigned short data_f;     // 2 Bytes
10
  unsigned short data_g;     // 2 Bytes
11
  unsigned short data_h;     // 2 Bytes
12
  unsigned char eof;         // 1 Byte
13
};
14
                            // in Summe: 18 Bytes

und genau das siehst du auch im Kontrollausdruck

> Mein header und eof sollten doch eigentlich char sein.

Sind sie doch auch.

68      <-- h für header
37  -+  <-- data_a
00  -+
37  ---+  <-- data_b
00  ---+
37  -+  <-- data_c
00  -+
37
00
37
00
37
00
37
00
37  -+   <-- data_h
00  -+
3b       <-- Simikolon

wiederrum in Summe 18 Bytes. Genau soviele, wie auch in der struct sind.
#1934930
Lesenswert?

Entschuldige bitte, wenn das jetzt harsch geklungen hat. Das war nicht 
die Absicht.
Aber im Moment verwirren wir ihn sonst. Das ist jetzt für ihn wichtig. 
Er lernt gerade den internen Aufbau von Datentypen. Auch wenn er es noch 
nicht weiß :-)

Die nächste lustige Hürde wird dann kommen, wenn ich ihn fragen werde, 
wie er auf der Zielmaschine sicherstellen will, dass er seinen Header 
aus einem Datenstrom zweifelsfrei herausfischen kann. Aber alles zu 
seiner Zeit. Jetzt muss sich erst mal die Erkentnis durchsetzen, dass 
die Zahl 300 nicht mehr in ein Byte passt, wohl aber in einen unsigned 
short; warum das so ist; und warum daher die Ausgabe nicht so aussieht 
wie er das eigentlich erwartet hätte.
#1934960
Lesenswert?

Daniel V. schrieb:
> Nuja, zumindest bei "%02i" hätte ich diese Wirkung. Bei Hexzahlen hab
> ich das noch nicht angewandt, sorry, dann liege ich falsch.

Auch dort nicht.

der 2-er sagt, dass die Ausgabe in einem Feld mit der Feldbreite 2 zu 
erfolgen hat und der 0-er sagt, dass anstelle von Leerzeichen führende 
0-en zum auffüllen benutzt werden sollen.

%02i   angewendet auf 5  ergibt eine Ausgabe von 05. Denn 05 ist 2 
Zeichen breit und anstelle eines Leerzeichens wurde eine führende 0 
eingefügt.

Brauchen kann man das zb bei Festkommaarithmetik

die Zahl 203 repräsentiere den Wert 2.03

Die Ausgabe sei dann
  int j = 203;
  printf( "%i.%02i", j / 100, j % 100 );

im 2.ten Teil, beim Modulo, ist es ganz wichtig, dass man führende 0en 
hat.
  printf( "%i.%i", j / 100, j % 100 );
würde sonst 2.3 ausgeben und das ist offensichtlich falsch.


Oder denk an Uhrzeiten. Bei den Stunden kann man noch darüber 
diskutieren, aber bei den Minuten hat man eigentlich meistens immer eine 
2 stellige Ausgabe

   00:00
   00:01
   00:50
   14:30

  printf( "%02i:%02i", hours, minutes );




Hmm. Es ist jetzt schon über eine halbe Stunde her. Ich glaub jetzt hat 
ers verstanden.
Gast #1935000
Lesenswert?

Leider nicht da ich anstelle von 18 Bytes 20 bekomme, da er nach jeden 
char noch 1 Byte hinzufügt.

Wenns jetzt so ein offensichtlicher Fehler ist ich sehe ihn leider 
momentan nicht.

Naja ich denk nochmal ganz in Ruhe drüber nach.
#1935003
Lesenswert?

TM schrieb:
> Leider nicht da ich anstelle von 18 Bytes 20 bekomme, da er nach jeden
> char noch 1 Byte hinzufügt.

Auf welchem Rechner?

Der Compiler darf Padding Bytes einfügen, um einzelne Mitglieder der 
Struktur aufgrund zb technologischer Beschränkungen auf bestimmte 
Adressen zu hieven (zb damit alles auf einer geraden Adresse anfängt)

Da du im GCC Forum gepostet hast, bin ich von einem AVR ausgegangen. Auf 
dem gibt es kein Padding.



(Ich muss jetzt leider weg. Bin eh schon spät drann)
#1935008
Lesenswert?

TM schrieb:
> Ist ein normaler Windows Rechner hab das programm eben in c++

Dann poste das bitte nächstes mal ins PC-Programmierung Forum. Dann gibt 
es keine Missverständnisse.

Du musst deine Compilerdoku durchforsten, wie du für diese Struktur das 
Padding abschalten kannst. Meistens ist das irgend ein Attribut oder ein 
#pragma (zb #pragma pack bei den Microsoft Compilern)
Gast #1935009
Lesenswert?

>Ist ein normaler Windows Rechner
Naja. nehmen wir dann also mal an das es sich um eine 80X86-Architektur 
handelt (obwohl Windows alleine das nicht zwingend erfordert).

Jedenfalls ist es nach dem C-Standard zulässig, (Du solltest doch mal 
ein C-Buch lesen) das der Compiler Bytes in die Struktur reinflickt um 
die Elemente der Struktur effizient zugreifbar zu machen.

Wenn Du das verhindern willst musst Du, #pragma pack verwenden.
Gast #1935028
Lesenswert?

>Ok wo finde ich raus auf welcher processorstrucktur welcher compiler das
>macht ?

Eine Übersicht dazu wird es sehr wahrscheinlich nicht geben.

Du hast glaube ich auch noch nicht verstanden, das die C-Regel so 
lautet: "Der Compiler kann beliebige Anzahlen von Bytes in die Struktur 
patchen."
Es gibt hingegen keine C-Regel die lautet, das man das abstellen kann.

So! Dann gibt es Compiler, die es erlauben mittels #pragma pack oder 
Optionen oder ähnlichem, dieses Verhalten zu unterbinden. D.h. Du musst 
in der Compilerdokumentation nachschauen ob des so eine Möglichkeit 
gibt. (Das hat ja auch Karl heinz schon geschrieben).
#1937372
Lesenswert?

Karl heinz Buchegger schrieb:
> Daniel V. schrieb:
>> Nuja, zumindest bei "%02i" hätte ich diese Wirkung. Bei Hexzahlen hab
>> ich das noch nicht angewandt, sorry, dann liege ich falsch.
>
> Auch dort nicht.
>
> der 2-er sagt, dass die Ausgabe in einem Feld mit der Feldbreite 2 zu
> erfolgen hat und der 0-er sagt, dass anstelle von Leerzeichen führende
> 0-en zum auffüllen benutzt werden sollen.
>
> %02i   angewendet auf 5  ergibt eine Ausgabe von 05. Denn 05 ist 2
> Zeichen breit und anstelle eines Leerzeichens wurde eine führende 0
> eingefügt.

Ja, das hab ich ja auch gemeint, weil er in sein short_int 55 
reingeschrieben hat und immer
37
00
37
00

bekommen hat, also "00" für die 0.

Aber offensichtlich gings um das "ffffffcc". Das hab ich völlig 
überlesen.
Allerdings hab ich gelernt, dass struct nicht gleich struct ist. Das war 
mir nicht so bewusst.
Hab nämlich schon oft Struct-Daten von AVR an den PC geschickt, also mit 
Zeiger auf  Struct, (über RS232) und das hat immer funktioniert...
Daniel

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren