mikrocontroller.net

Forum: Compiler & IDEs struct mit printf ausgeben


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
ich stehe gerade etwas auf dem Schlauch mit printf(). String-Ausgabe ist 
klar. Aber wie kann man damit Strukturen ausgeben?

Ich habe eine struct definiert (im RAM) und möchte die quasi als 
memory-Dump ausgeben. Also aus einem (char)0 soll auch das 
nichtdruckbare Zeichen werden, nicht '0'.
Quasi etwas wie WriteFile(hFile, &struct, sizeof(struct), ...);

Ausgangspunkt ist GCC für AVR. Hoffentlich keine Infos vergessen.
Die Lösung ist wahrscheinlich trivial, aber printf(struct) gibt immer 
den Fehler "incompatible type of argument 1".

Andy

Autor: Michael Rathmair (dj_motionx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo !

Schreib dir eine Konvertierungsfunktion für deine Struktur. Da kannst du 
dann genau anpassen was wie und in welcher Reihenfolge alle 
Strukturelemente ausgegeben werden. Ergebnis ist ein String dem du dann 
printf übergibst.

L.g. Michi

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja die Lösung ist trivial - es gibt keine.

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

Bewertung
0 lesenswert
nicht lesenswert
Andy schrieb:

> ich stehe gerade etwas auf dem Schlauch mit printf(). String-Ausgabe ist
> klar. Aber wie kann man damit Strukturen ausgeben?

printf kannst du nur dann benutzen, wenn es entsprechende 
Formatieranweisungen im Formatstring für das Auszugebende gibt. Das sind 
alle "eingebauten" Datentypen.

Eine struct besteht ja aus Membern, die letztendlich alle von einem der 
eingebauten Basistypen sind.

Und: Mit printf erzeugt man immer eine Textausgabe.

> Ich habe eine struct definiert (im RAM) und möchte die quasi als
> memory-Dump ausgeben.

Das ist aber etwas ganz anderes und hat mit Textausgabe nichts mehr zu 
tun.

> Also aus einem (char)0 soll auch das
> nichtdruckbare Zeichen werden, nicht '0'.

Du brauchst erst mal eine Basisfunktion, die dir ein einzelnes Byte 
rausgibt. Wie diese Funktion aussieht hängt von deiner Umgebung ab. 
putchar ist schon mal ein guter Ansatzpunkt

Und dann brauchst du noch eine Funktion, die einen Speicherbereich 
sukzessive an putchar verfüttert
void putmem( void* memory, size_t size )
{
  uint8_t memAsByte = (uint8_t) memory;
  size_t i;

  for( i = 0; i < size; ++i )
    putchar( *memAsByte ++ );
}

Damit hast du schon alle Bestandteile zusammen. Du musst nur noch eine 
Variable an putmem 'verfüttern'.
 struct irgendwas myVar;

 ..

 putmem( myVar, sizeof( myVar ) );

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fwrite() nach stdout.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einen Pointer auf den Struct in einen Pointer auf char casten, und dann 
Zeichen für Zeichen per putc ausgeben.

Oliver

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Quasi etwas wie WriteFile(hFile, &struct, sizeof(struct), ...);

fwrite(&struct, sizeof(struct), 1, stdout);

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
erst einmal herzlichen Dank für die vielen Antworten!

Das ganze als lesbaren String auszugeben war nicht Sinn der Sache. 
Momentan arbeite ich in einem (leider fremden) Programm an einer kleinen 
Erweiterung, mit der ich ein struct an eine andere Maschine übergeben 
möchte. Eigentlich ganz simpel.
Da die zugehörige Schnittstelle sowieso auf stdout abgebildet wird und 
es im bisherigen Prog keine WriteBuffer()-Funktion o.ä. gibt, war printf 
mein erster Ansatz. Hatte da das Windows WriteFile() im Hinterkopf.
Daher kommt mir der Vorschlag mit fwrite() am nächsten. Daß ich da nicht 
selbst drauf gekommen bin...  ts ts
(Naja, normalerweise meide ich die IO-Streams...)

Nochmals Danke an alle & einen schönen Abend!
Andy

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andy schrieb:
> Das ganze als lesbaren String auszugeben war nicht Sinn der Sache.
> Momentan arbeite ich in einem (leider fremden) Programm an einer kleinen
> Erweiterung, mit der ich ein struct an eine andere Maschine übergeben
> möchte. Eigentlich ganz simpel.

Es ist nicht wirklich empfehlenswert, structs einfach so wie sie im 
Speicher stehen an eine andere Maschine zu senden, denn das funktioniert 
nur solange die beiden Maschinen die gleiche (oder eine halbwegs 
ähnliche) Architektur haben.

Sobald die beiden Maschinen sich zu sehr unterscheiden (Byte Order, 
Wortbreite z.B., aber ggf. sogar schon bei unterschiedlichen 
Compileroptionen!), kann das Speicherlayout der struct sich 
unterscheiden, auch wenn beide Male derselbe Sourcecode kompiliert wird, 
und dann funktioniert die Kommunikation nicht mehr.

Besser ist es, die Felder einzeln der Reihe nach in definierter Form zu 
übertragen, also mit definierter Bitbreite, Byte-Reihenfolge etc. Das 
kann ruhig in binärer Form geschehen, nur eben in einer einheitlichen, 
architekturunabhängigen Form. Damit gibt es dann auch in der Zukunft, 
bei Rechnerupgrades, neuen Compilerversionen etc. keine Probleme.

Aufgrund dieser Problematik gibt es überhaupt Begriffe wie "Network Byte 
Order" und "Host Byte Order", und stellt z.B. das Unix-Socket-API 
Funktionen wie htonl() und ntohl() zur Verfügung, die zwischen den 
beiden umwandeln.

Andreas

Autor: tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie schon erwähnt, memory aligning/padding durch den compiler und byte 
order (Big Endianvs. little endian) durch den verwendeten uC/uP können 
zum fallstrick werden, wenn man solch eine struktur zur Kommunikation 
verwenden möchte und die einfach byteweise übermittelt...

Abhilfe wäre z.B mit sprintf() die einzelnen Elemente formatiert in 
einen string ausgeben, den übermitteln und auf der rx-seite per sscanf() 
mit gleicher formatierung wieder in Strukturelemente holen. Allerdings 
fressen die lib-funktionen der printf und scanf familie gerne laufzeit 
und code...

Es hilft nur ein klar definiertes telegrammformat als robuster und 
sicherer ansatz...

gruss, tom.

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.