Forum: Compiler & IDEs struct mit printf ausgeben


von Andy (Gast)


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

von Michael R. (dj_motionx)


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

von Peter (Gast)


Lesenswert?

ja die Lösung ist trivial - es gibt keine.

von Karl H. (kbuchegg)


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
1
void putmem( void* memory, size_t size )
2
{
3
  uint8_t memAsByte = (uint8_t) memory;
4
  size_t i;
5
6
  for( i = 0; i < size; ++i )
7
    putchar( *memAsByte ++ );
8
}

Damit hast du schon alle Bestandteile zusammen. Du musst nur noch eine 
Variable an putmem 'verfüttern'.
1
 struct irgendwas myVar;
2
3
 ..
4
5
 putmem( myVar, sizeof( myVar ) );

von Hc Z. (mizch)


Lesenswert?

fwrite() nach stdout.

von Oliver (Gast)


Lesenswert?

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

Oliver

von Rolf Magnus (Gast)


Lesenswert?

> Quasi etwas wie WriteFile(hFile, &struct, sizeof(struct), ...);

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

von Andy (Gast)


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

von Andreas F. (aferber)


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

von tom (Gast)


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.

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.