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
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
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
voidputmem(void*memory,size_tsize)
2
{
3
uint8_tmemAsByte=(uint8_t)memory;
4
size_ti;
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'.
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
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
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.