Forum: Compiler & IDEs printf oder lieber sprintf?


von Ralf (Gast)


Lesenswert?

Hallo,

auf einem Microcontroller (hier ARM Cortex M3 mit GCC und newlib) 
funktioniert printf ja nicht out-of-the-box, wenn der 
Controllerhersteller nicht schon passende Funktionen für _write, etc. 
zur Verfügung stellt. Ruft man dann printf auf, dann fliegen einem 
Fehlermeldungen bzgl fehlender Funktionen wie eben _write, _sbrk, etc um 
die Ohren.
Diese Funktionen muss man dann selber passend für den µC implementieren.

Hierzu hätte ich folgende Fragen:
1) mit sprintf landet die Ausgabe in einem Buffer, welchen man dann 
passend an die jeweilige Schnittstelle übergeben kann. Wenn ich nun 
davon ausgehe, dass die Software nicht auf einen PC portiert wird, 
dann gibt es eigentlich keinen Grund, die oben genannten Funktionen zu 
implementieren, oder? Falls die Software doch auf einem PC (oder 
generell auf einem völlig anderen System) laufen soll, dann sollte man 
es aber tun, damit man überall printf verwenden kann, korrekt?
2) Wie schwer ist die Implementierung, wenn man auf dem µC evtl mehrere 
Schnittstellen wie z.B. mehrere UARTs und ein Display hat, die man per 
printf ansprechen möchte? Neben den Zugriffsfunktionen (_write, etc.) 
müsste man dann ja noch die Schnittstellen selbst definieren, wie 
funktioniert das dann?

Ralf

von Günter R. (galileo14)


Lesenswert?

Benutze doch besser fprintf. Dort kannst du einen File-Control-Block 
angeben, der zur Ausgabe benutzt werden soll. Dann können beliebig viele 
UARTs angesprochen werden oder LCDs, deren Ausgabefunktionen du 
allerdings natürlich schreiben bzw. beistellen mußt. Im 
File-Control-Block stehen u.a. die Adressen der Ein/Ausgabefunktionen, 
die du dort reinschreiben mußt, ggf. durch Funktionen wie fopen. Siehe 
Doku.

von guest (Gast)


Lesenswert?

Ne Art von '_write' mußt Du sowieso implementieren, irgendwie muß Du 
Deinen Buffer ja auch auf die Schnittstelle schreiben.
Und sprintf geht auch auf dem PC problemlos. Der Portierungsaufwand zum 
PC ist nahezu derselbe, egal ob printf oder sprintf. sprintf könnte da 
sogar von Vorteil sein, eventuell will man ja auch am PC die Daten auf 
eine serielle Schnitstelle schreiben. Am flexibelsten dürfte die 
Variante von Günter sein.

von Markus (Gast)


Lesenswert?

printf ist ja offensichtlich untrennbar an die Funktionen _write, _sbrk 
etc. gekoppelt. Das bekommst Du nicht entkoppelt, und zur Laufzeit auf 
unterschiedliche Ausgabegeräte auch nicht umgelenkt.

Mit fprintf ginge das eher, da es unterschiedliche Ausgabegeräte 
bedienen kann. Hat Günter schon beschrieben.

Wenn Du dasselbe Modul auf unterschiedliche Geräte schreiben lassen 
möchtest, brauchst Du dafür ein Interface. Das Interface definiert die 
Funktionen. Das benutzt Du in diesem Modul und reichst von außen die 
gerätespezifische Implementierung dieses Interfaces hinein oder erfragst 
es per Callback.

In C wäre das ein File Pointer, in C++ würde man sich für jedes Gerät 
einen eigenen Output Stream implementieren, in Java einen Writer. Zum 
printf-like Formatieren in C++ braucht es Zusatzklassen (sprintf könnte 
genügen), in Java gäbe es dazu den PrintWriter, der u.a. einen Writer 
formatiert beschreiben kann.

von Hans (Gast)


Lesenswert?

Der Nachteil an sprintf ist, dass Du die Größe des Puffers vorher 
festlegen musst. Mit printf bzw. fprintf kannst Du dagegen beliebig 
lange und kurze Daten effizient ausgeben, indem Du jedes Zeichen live 
rausschreibst.

Von daher lohnt es sich imo schon, die benötigten Funktionen zu 
implementieren. Für die Variante mit sprintf brauchst Du ja am Ende auch 
eine Funktion, die den fertigen String ausgibt, typischerweise bestehend 
aus einer Schleife über alle Zeichen und der Ausgabe des Zeichens. 
Diesen Code in ein _write zu verpacken, dürfte kein großer Aufwand zu 
sein.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?


von Rolf M. (rmagnus)


Lesenswert?

Hans schrieb:
> Der Nachteil an sprintf ist, dass Du die Größe des Puffers vorher
> festlegen musst.

Und dass man überhaupt einen Puffer braucht, der so groß ist, daß die 
Ausgabe des sprintf-Aufrufs vollständig reinpasst. Dementsprechend viel 
Speicher verschwendet man damit ggf.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Die Anzahl auszugebender Bytes kann mit snprintf bestimmt werden, danach 
kann temporärer Speicher dafür zur Verfügung gestellt werden, z.B. per 
alloca auf dem Stack oder per malloc auf dem Heap.

Schön ist das aber nicht; wenn man nicht aus anderen Gründen die Ausgabe 
als String benötigt, sollte man auf diesen Zwischenschritt verzichten.

Fehlendes _sbrk deutet eher auf ein Fehlendes OS hin, printf durch 
sprintf ersetzen ändert nix daran.  Stellt die libgloss kein _sbrk zur 
Verfügung? Oder verwendest du libnosys?

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.