mikrocontroller.net

Forum: Compiler & IDEs struct zu char array casten


Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
struct data
{
  unsigned short header;
  unsigned short data_a;
  unsigned short data_b;
  unsigned short data_c;
  unsigned short data_d;
  unsigned short data_e;
  unsigned short data_f;
  unsigned short data_g;
  unsigned short data_h;
  unsigned short eof;
};

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

Autor: Daniel V. (danvet)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include "stdafx.h"
struct data
{
  unsigned char header;
  unsigned short data_a;
  unsigned short data_b;
  unsigned short data_c;
  unsigned short data_d;
  unsigned short data_e;
  unsigned short data_f;
  unsigned short data_g;
  unsigned short data_h;
  unsigned char eof;
};

int main(int argc, char* argv[])
{
  struct data Daten;
  char *p_Char;
  Daten.data_a=55;
  Daten.data_b=55;
  Daten.data_c=55;
  Daten.data_d=55;
  Daten.data_e=55;
  Daten.data_f=55;
  Daten.data_g=55;
  Daten.data_h=55;
  Daten.eof =';';
  Daten.header='h';
  p_Char = (char*)Daten;
  //printf("%s",p_Char);
  return 0;
}

Autor: Marius Wensing (mw1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TM schrieb:
> Allerdings meckert er bei dem cast :(

Und was meckert er?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TM schrieb:
> p_Char = (char*)Daten;

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

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
#include "stdafx.h"
struct data
{
  unsigned char header;
  unsigned short data_a;
  unsigned short data_b;
  unsigned short data_c;
  unsigned short data_d;
  unsigned short data_e;
  unsigned short data_f;
  unsigned short data_g;
  unsigned short data_h;
  unsigned char eof;
};
int i;
int main(int argc, char* argv[])
{
  struct data Daten;
  char *p_Char;
  Daten.data_a=55;
  Daten.data_b=55;
  Daten.data_c=55;
  Daten.data_d=55;
  Daten.data_e=55;
  Daten.data_f=55;
  Daten.data_g=55;
  Daten.data_h=55;
  Daten.eof =';';
  Daten.header='h';
  p_Char =  (char*)&Daten;
  printf("%s",p_Char);
  scanf("%i",&i);
  return 0;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eigentlich wollte ich mir den gesamten Frame nochmal ausgeben.

Autor: Stefan Hennig (stefanhennig)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
  for( i = 0; i < sizeof( struct data ); ++i )
    printf( "%02x ", p_Char[i];
  printf( "\n" );

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include "stdafx.h"
struct data
{
  unsigned char header;
  unsigned short data_a;
  unsigned short data_b;
  unsigned short data_c;
  unsigned short data_d;
  unsigned short data_e;
  unsigned short data_f;
  unsigned short data_g;
  unsigned short data_h;
  unsigned char eof;
};
int i;
int main(int argc, char* argv[])
{
  char Datapacket[18];
  struct data Daten;
  char *p_Char;
  Daten.data_a=55;
  Daten.data_b=55;
  Daten.data_c=55;
  Daten.data_d=55;
  Daten.data_e=55;
  Daten.data_f=55;
  Daten.data_g=55;
  Daten.data_h=55;
  Daten.eof =';';
  Daten.header='h';
  p_Char =  (char*)&Daten;
  for( int x = 0; x <sizeof( struct data );x++ )
  {
  printf("%02x",p_Char[x]);
  printf("\n");
  }
  scanf("%i",&i);
  return 0;
}

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal wieder: C-Buch lesen und verstehen!

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel V. (danvet)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel V. (danvet)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
struct data
{
  unsigned char header;      // 1 Byte
  unsigned short data_a;     // 2 Bytes
  unsigned short data_b;     // 2 Bytes  
  unsigned short data_c;     // 2 Bytes
  unsigned short data_d;     // 2 Bytes
  unsigned short data_e;     // 2 Bytes
  unsigned short data_f;     // 2 Bytes
  unsigned short data_g;     // 2 Bytes
  unsigned short data_h;     // 2 Bytes
  unsigned char eof;         // 1 Byte
};
                            // 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.

Autor: Daniel V. (danvet)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel V. (danvet)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: TM (Gast)
Datum:

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

Gruß Tobias

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: TM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar danke an alle ;)

Autor: Daniel V. (danvet)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.