Forum: Compiler & IDEs struct zu char array casten


von TM (Gast)


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

von Daniel V. (danvet)


Lesenswert?

data Daten;    // Daten-Struktur erzeugen

char *p_Char;  // Zeiger auf Char

p_Char = (char*)Daten;  // Zeiger richtig setzen

PutUART(p_Char[0]);
PutUART(p_Char[1]);
.
.
PutUART(p_Char[n]);


Oder so ähnlich ;-)

von TM (Gast)


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
}

von Marius W. (mw1987)


Lesenswert?

TM schrieb:
> Allerdings meckert er bei dem cast :(

Und was meckert er?

von Klaus W. (mfgkw)


Lesenswert?

TM schrieb:
> p_Char = (char*)Daten;

es müsste ja auch heißen:
p_Char = (char*)&Daten;

von TM (Gast)


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
}

von Karl H. (kbuchegg)


Lesenswert?

TM schrieb:

>   printf("%s",p_Char);

Nur weil du etwas zu einem char* umcastest, ist das noch lange kein 
String. Ein Trabbi wird schliesslich auch nicht zu einem Ferrari, wenn 
ich ein springendes Pferd draufklebe.

Was willst du wirklich machen?

von TM (Gast)


Lesenswert?

Eigentlich wollte ich mir den gesamten Frame nochmal ausgeben.

von Stefan H. (stefanhennig)


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?

von Karl H. (kbuchegg)


Lesenswert?

TM schrieb:
> Eigentlich wollte ich mir den gesamten Frame nochmal ausgeben.

Dann tu das. Aber du musst berücksichtigen, dass du keinen String hast. 
Also kannst du auch keine Stringfunktionen benutzen.
1
  for( i = 0; i < sizeof( struct data ); ++i )
2
    printf( "%02x ", p_Char[i];
3
  printf( "\n" );

von Karl H. (kbuchegg)


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?

von TM (Gast)


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
}

von Klaus W. (mfgkw)


Lesenswert?

Mal wieder: C-Buch lesen und verstehen!

von TM (Gast)


Lesenswert?

Nein ich möchte keine ASCII Übertragung machen.
Aussehen soll es wie folgt:

Header -- Daten1 --... Daten8 -- EOF

1 Byte -- 2 Byte --... 2 Byte -- 1Byte

von Karl H. (kbuchegg)


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.

von Daniel V. (danvet)


Lesenswert?

TM schrieb:

>   printf("%02x",p_Char[x]);
> [/c]

Ich würde das 02 weglassen, sonst schreibt er dir immer 2 Nullen 
vorneweg..(bzw in deiner Darstellung hinten dran)

von Karl H. (kbuchegg)


Lesenswert?

Daniel V. schrieb:
> TM schrieb:
>
>>   printf("%02x",p_Char[x]);
>> [/c]
>
> Ich würde das 02 weglassen, sonst schreibt er dir immer 2 Nullen
> vorneweg..(bzw in deiner Darstellung hinten dran)

Keinesfalls.
Lies in deinem C Buch über Formatiermöglichkeiten im printf Formatstring 
nach. Die für ihn überzähligen 00 haben nichts damit zu tun.

von TM (Gast)


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.

von Daniel V. (danvet)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

TM schrieb:
> 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 ?

Mal wieder: C-Buch lesen und verstehen!

von Karl H. (kbuchegg)


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.

von Daniel V. (danvet)


Lesenswert?

probiers mal mit:
printf("%c",p_Char[x]);

von Karl H. (kbuchegg)


Lesenswert?

Daniel V. schrieb:
> probiers mal mit:
> printf("%c",p_Char[x]);


Daniel halt dich bitte raus. Du bist auf dem Holzweg. Sein gedankliches 
Problem liegt ganz woanders.

von Daniel V. (danvet)


Lesenswert?

Karl heinz Buchegger schrieb:
> Daniel V. schrieb:
>> probiers mal mit:
>> printf("%c",p_Char[x]);
>
>
> Daniel halt dich bitte raus. Du bist auf dem Holzweg. Sein gedankliches
> Problem liegt ganz woanders.

OK,bin ja auch schon im Feierabend ;-)

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von TM (Gast)


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.

von Karl H. (kbuchegg)


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)

von TM (Gast)


Lesenswert?

Ist ein normaler Windows Rechner hab das programm eben in c++ 
hingeschrieben weils mir halt wirklich nur um die Structs ging.

Gruß Tobias

von Karl H. (kbuchegg)


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)

von Huch (Gast)


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.

von TM (Gast)


Lesenswert?

Hey,

Ja ist eine x86 strucktur.
Ok wo finde ich raus auf welcher processorstrucktur welcher compiler das 
macht ?

Welches C oder C++ Buch wäre den da zu empfehlen wo auch solche Sachen 
mit drinstehen?

von Huch (Gast)


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

von TM (Gast)


Lesenswert?

Alles klar danke an alle ;)

von Daniel V. (danvet)


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

von Karl H. (kbuchegg)


Lesenswert?

Daniel V. schrieb:

> Aber offensichtlich gings um das "ffffffcc". Das hab ich völlig
> überlesen.

Ich auch.
Ich habs für das Echo einer voreiligen Eingabe gehalten.

Nimmt man alles zusammen, dann ergibt es Sinn. Sofern man weiß, dass das 
Programm auf einem PC gelaufen ist. Ohne dieses Wissen allerdings ergibt 
der Dump keinen Sinn.

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.