Forum: PC-Programmierung printf ersetzen


von Gabelstapler1000 (Gast)


Lesenswert?

hi ich habe in meinem code ein printf... es wird aber gar nicht 
ausgeführt, weil der controller damit nichts anfangen kann. Am liebsten 
würde ich einfach das printf überschreiben, ohne dass alle printfs 
umbenannt werden müssen in printf_works().
geht das?

von Sebastian R. (sebastian_r569)


Lesenswert?

Gabelstapler1000 schrieb:
> weil der controller damit nichts anfangen kann

Die richtige Lösung wäre, das hier zu ändern und den Standardstream 
(stdout/stdin) auf die funktionierenden Kommunikationsfunktionen zu 
lenken

von Rolf M. (rmagnus)


Lesenswert?

Gabelstapler1000 schrieb:
> hi ich habe in meinem code ein printf... es wird aber gar nicht
> ausgeführt, weil der controller damit nichts anfangen kann.

Warum löschst du es dann nicht einfach aus deinem Code? Und was heißt 
"nichts anfangen kann"? Ist in der Lib für deinen unbekannten Controller 
kein printf definiert? Dann kannst du auch einfach selbst eins 
definieren, das dann tut, was immer du willst.

von Gabelstapler1000 (Gast)


Lesenswert?

Sebastian R. schrieb:
> Die richtige Lösung wäre, das hier zu ändern und den Standardstream
> (stdout/stdin) auf die funktionierenden Kommunikationsfunktionen zu
> lenken

interessant
weiß jmd wie das geht xD

von Sebastian R. (sebastian_r569)


Lesenswert?

Gabelstapler1000 schrieb:
> weiß jmd wie das geht xD

Kommt drauf an.

Wir wissen ja nicht, auf welcher Plattform du entwickelst und wo dann 
die Ausgabe stattfinden soll.

von A. S. (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> Am liebsten würde ich einfach das printf überschreiben, ohne dass alle
> printfs umbenannt

Wieso überschreiben?

Tut der Controller nix? Gibt es eine Fehlermeldung? Hast du ein anderes 
printf was funktioniert?

Hast Du eine Ausgabe? (Seriell, Display, morsebeeper?)

von temp (Gast)


Lesenswert?

oder ein Makro definieren:
1
#ifdef printf
2
  #undef printf
3
#endif
4
#define printf(...)

oder eine Funktion schreiben mit dem Namen printf die nichts tut.
1
int printf(const char *format, ...)
2
{
3
  return 0;
4
}

Welcher Weg bei dir funktioniert hängt vom Compiler und den Libs ab. 
Dazu hast du uns aber nichts verraten.

von Nachdenklicher (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> interessant
> weiß jmd wie das geht xD

In meinen AVR-Projekten habe ich dafür meine eigene (abgespeckte) 
printf-Bibliothek, der ich beim Programmstart einmal einen Zeiger auf 
eine Ausgaberoutine übergebe. Diese macht nichts weiter, als ein 
einzelnes Zeichen auszugeben, printf ruft sie dann auf, wenn man es 
nutzt. Dabei ist es für printf völlig egal, ob die Ausgaberoutine jedes 
Mal wartet, bis das Senderegister leer ist und direkt schreibt, oder ein 
Sendepuffer dazwischen hängt. Auch welcher Ausgabekanal genutzt wird, 
ist für printf damit egal. (Bei meinen AVRs kann das prinzipiell 
entweder ein UART oder, falls vorhanden, ein Display sein - so kann ich 
für beide, abgesehen von der Ausgaberoutine, den gleichen Code nutzen. 
Wenn man Spaß dran hat, kann man als Ausgaberoutine auch den Text mit 
einer LED morsen lassen...;-) )

Bei der Arbeit hat unsere ARM-Toolchain entsprechende putchar-Routinen 
als "weak definition", die sich also einfach durch eigenen Code ersetzen 
lassen. tut man das nicht, landet es in der Konsole des Debuggers, 
alternativ setzt man dort eben seinen Sendecode für welche Schnittstelle 
auch immer ein.

Die ganzen Standard-I/O-Geschichten werden halt auf größeren Systemen 
vom Betriebssystem gehandelt, auf Mikrocontrollern wo man keins (oder 
vielleicht nur eine Scheduler-Bibliothek für mehrere Threads) hat, muß 
man den Spaß halt selbst basteln.

von Rolf M. (rmagnus)


Lesenswert?

Nachdenklicher schrieb:
> In meinen AVR-Projekten habe ich dafür meine eigene (abgespeckte)
> printf-Bibliothek, der ich beim Programmstart einmal einen Zeiger auf
> eine Ausgaberoutine übergebe. Diese macht nichts weiter, als ein
> einzelnes Zeichen auszugeben, printf ruft sie dann auf, wenn man es
> nutzt. Dabei ist es für printf völlig egal, ob die Ausgaberoutine jedes
> Mal wartet, bis das Senderegister leer ist und direkt schreibt, oder ein
> Sendepuffer dazwischen hängt. Auch welcher Ausgabekanal genutzt wird,
> ist für printf damit egal.

All das ist doch in der avr-libc schon drin.

von Gabelstapler1000 (Gast)


Lesenswert?

A. S. schrieb:
> Wieso überschreiben?
code nicht ändern
> Tut der Controller nix? Gibt es eine Fehlermeldung? Hast du ein anderes
ignoriert es
> printf was funktioniert?
ja uart
> Hast Du eine Ausgabe? (Seriell, Display, morsebeeper?)
ja putty ( uart)


werde zuerst mal das Makro testen :D

von Oliver S. (oliverso)


Lesenswert?

Gabelstapler1000 schrieb:
>> printf was funktioniert?
> ja uart

Was jetzt? Schreibt printf was auf die uart? Wenn ja, wo ist dann die 
Frage?

Wenn nein, und dein Code an sich kompiliert, aber der Prozessor "mit 
printf nichts anfangen kann", dann wird die c-standardlib deiner 
unbekannten toolchain zu deinem unbekannten Prozessor ein printf 
mitbringen. Und sehr wahrscheinlich musst du dem irgendwie beibringen, 
wohin das die Ausgabezeichen schreiben soll, denn ansonsten, wie du ja 
festgestellt hast, tut sich da einfach gar nichts.

Wie das geht, steht in der Doku zu deiner c-standardlib.

Oliver

: Bearbeitet durch User
von Gabelstapler1000 (Gast)


Lesenswert?

Scheint zu klappen mit dem Makro!!!!!!

Ich was ich dabei mache ist:
1
char array[12312];
2
#define printf(...)                            \
3
    sprintf(array, __VA_ARGS__); \
4
    uart("\r\n");              \
5
    uart(array)
Es kommt allerdings noch ein Fehler bei falschen Formaten.
Weiß nicht ob der Autor des Codes da Fehler reingemacht hat.
Wenn ich jedoch anstatt %d, %ld schreibe geht das wieder.


 error: format '%d' expects argument of type 'int'

Da ich aber das ebenfalls nicht ändern möchte frage ich mich ob man das 
umgehen kann?

von Gabelstapler1000 (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> Da ich aber das ebenfalls nicht ändern möchte frage ich mich ob man das
> umgehen kann?

das ist halt sehr unnötig sowas xD

von Rolf M. (rmagnus)


Lesenswert?

Gabelstapler1000 schrieb:
> Es kommt allerdings noch ein Fehler bei falschen Formaten.

Das ist doch gut!

> Weiß nicht ob der Autor des Codes da Fehler reingemacht hat.

Ich dachte, es sei dein Code?

> Wenn ich jedoch anstatt %d, %ld schreibe geht das wieder.
>
>  error: format '%d' expects argument of type 'int'

Offenbar ist der übergebene Parameter nicht vom Typ int.

> Da ich aber das ebenfalls nicht ändern möchte frage ich mich ob man das
> umgehen kann?

Du willst, dass das Programm das richtige tut, obwohl die 
Format-Specifier falsch sind? Was glaubst du, warum man die angeben 
muss?

von Gabelstapler1000 (Gast)


Lesenswert?

Ja ich verwende einen fremden Code.
Möchte/sollte da so wenig wie möglich ändern.

Rolf M. schrieb:
> Du willst, dass das Programm das richtige tut, obwohl die
> Format-Specifier falsch sind? Was glaubst du, warum man die angeben
> muss?

Man muss die angeben, damit die Datei die man übergibt korrekt 
verarbeitet/ dargestellt wird (also über printf).
Im Code soll z.B. u32 mit %d ausgegeben werden


Oh ich habe das gerade mal woanders getestet--- Da scheint das aber zu 
gehen!
Hab das sogar so wie im Code mit zwei typedefs gemacht...
1
#include <stdio.h>
2
#include <stdint.h>
3
typedef uint32_t u32 ;
4
typedef u32 superformat_t ;
5
6
int main()
7
{
8
    superformat_t d =23;
9
    printf("Hello World");
10
    printf ("%d",d);
11
    return 0;
12
}
Hello World23

...Program finished with exit code 0
Press ENTER to exit console.

von demo (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> Ja ich verwende einen fremden Code.
> Möchte/sollte da so wenig wie möglich ändern.

%d und %i stehen für int. Der ist auf dem avr aber nur 16bit. Wird dem 
ein 32bit Wert und %d übergeben kommt der fehler.

Bei deinem Konsoleprogramm ist %d aber für 32bit int. Deshalb geht das 
da.

von Rolf M. (rmagnus)


Lesenswert?

Gabelstapler1000 schrieb:
> Hab das sogar so wie im Code mit zwei typedefs gemacht...

Die typedefs spielen keine Rolle.

> #include <stdio.h>
> #include <stdint.h>
> typedef uint32_t u32 ;
> typedef u32 superformat_t ;
> int main()
> {
>     superformat_t d =23;
>     printf("Hello World");
>     printf ("%d",d);
>     return 0;
> }
> Hello World23

Klar kann das funktionieren. Es hängt letztendlich von der Zielplattform 
ab. Für Typen wie uint32_t sollte man aber nicht "%d", sondern "%" 
PRIu32 verwenden. Das ist zwar etwas sperrig, aber unabhängig von der 
Plattform dann immer korrekt.

von Gabelstapler1000 (Gast)


Lesenswert?

demo schrieb:
> Der ist auf dem avr aber nur 16bit.

ah ok , das könnte der Grund sein.
Habe zwar einen ARM M3 aber vlt. ist das ja ähnlich.

von Gabelstapler1000 (Gast)


Lesenswert?

bzw. ich teste das mal in meinem Programm:
1
//Geht:
2
  uint16_t zahl =44;
3
  printf("%d",zahl);
4
//Geht nicht:
5
  uint32_t zahl =44;
6
  printf("%d",zahl);

von Gabelstapler1000 (Gast)


Lesenswert?

hmm..
jetzt kann mein Makro das zwar umsetzen, kommt aber noch nicht auf 
diesen einen Fall klar.
Also %d, uint32_t passt einfach nicht für die Zielplattform. Da gab es 
noch so was mit %x. Aber gleiches Thema.
..
Hmm ob man das wohl noch ändern kann..

von Gabelstapler1000 (Gast)


Lesenswert?

haha vlt.:
1
#undef %d 
2
#define %d %ld

von Gabelstapler1000 (Gast)


Lesenswert?

aber das würde ja auch die umändern die so bleiben sollen xD

von Master-Jimmy (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> Habe zwar einen ARM M3 aber vlt. ist das ja ähnlich.

Evtl. hast du ja einen STM32?? Ich weiss nämlich gerade nicht, wie 
"generisch" folgende Lösung, welche ich normalerweise benutze, ist:
1
/*!
2
 * \brief Redirects standard output to the serial port.
3
 * \param ch data/character to be written
4
 */
5
void __io_putchar(int ch) {
6
  while(!(USART2->ISR & USART_ISR_TXE));
7
  USART2->TDR = ch;
8
}
(__io_putchar(int) ist "weak" definiert)

von Gabelstapler1000 (Gast)


Lesenswert?

ne habe keinen STM32
hmm also wie gesagt printf kann ich ja jetzt ersetzen mit dem Makro.

Mein Problem ist nun, dass wenn ich %d angebe und eine u32 Variable habe 
eine Fehler kommt.

Wenn ich jetzt alle mit #define %d %ld  umwandle weiß ich nicht ob das 
sinnvoll ist.
obwohl ich muss das doch mal testen.

was meinst du mit deiner Funktion __io_putchar
Wann wird die verwendet?

von Rolf M. (rmagnus)


Lesenswert?

Gabelstapler1000 schrieb:
> ne habe keinen STM32
> hmm also wie gesagt printf kann ich ja jetzt ersetzen mit dem Makro.
>
> Mein Problem ist nun, dass wenn ich %d angebe und eine u32 Variable habe
> eine Fehler kommt.

Es gibt einfach keinen wirklich sinnvollen Weg, damit umzugehen.

> Wenn ich jetzt alle mit #define %d %ld  umwandle weiß ich nicht ob das
> sinnvoll ist.

Nein, denn das funktioniert nicht.

von mh (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> Mein Problem ist nun, dass wenn ich %d angebe und eine u32 Variable habe
> eine Fehler kommt.
>
> Wenn ich jetzt alle mit #define %d %ld  umwandle weiß ich nicht ob das
> sinnvoll ist.
> obwohl ich muss das doch mal testen.
Was war nochmal der Grund warum du nicht gleich das richtige 
hinschreibst?

von W.S. (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> hi ich habe in meinem code ein printf... es wird aber gar nicht
> ausgeführt, weil der controller damit nichts anfangen kann.

Hä?
Warum hast du das dann erst in deinen Quellcode hineingeschrieben?
Ich schätze mal, es ist gar nicht dein Quellcode, sondern irgendwas, das 
du irgendwo im Internet 'weggefunden' hast, ohne es bislang selber zu 
verstehen.

Mein Rat wäre hier: versuche doch zu allererst, das von dir Gefundene zu 
verstehen. Danach haben sich zumeist 99% aller Probleme wie von selbst 
geklärt.

Ganz allgemein: Für Textausgaben beliebiger Art kann man 3 Wege 
beschreiten:
a) die gewünschten Ausgaben werden vom Compiler in ihre Teile zerlegt 
und der jeweils zugehörige Maschinencode generiert. Pascal macht das so 
bei der 'write'-Prozedur.
b) fast wie a), allerdings macht man das Zerlegen selber. Das geht mit 
eigentlich allen Programmiersprachen, auch mit C.
c) man benutzt eine Prozedur wie 'printf', die ihrerseits eine 
Textinterpreter beinhaltet. Dieser zerlegt den Formatstring - und das 
nicht etwa zur Übersetzungszeit, sondern zur Laufzeit. Hier wird also 
etwas zur Laufzeit gemacht, was besser zur Übersetzungszeit hätte 
gemacht werden sollen. So aber kostet das sowohl Speicherplatz als auch 
Ablaufgeschwindigkeit. Der einzige Vorteil (wenn man das als Vorteil 
ansieht) besteht darin, daß der Compiler besagte Zerlegung nicht zu 
können braucht. Alles andere bei 'printf' ist nur ein Haufen Nachteile. 
Dazu zählen nicht nur Speicherplatz und Laufzeit, sondern auch solche 
Dinge wie variable Anzahl von Funktionsargumenten usw.

Wie gesagt, man kann auch beim Programmieren mit C die Version b) 
benutzen und damit eine größere Effektivität der erzeugten Firmware 
erzielen, der Preis dafür ist allerdings etwas mehr Arbeit beim 
Schreiben der Quellen. Allerdings ist den typischen C Programmierern 
ihre persönliche Schreibfaulheit wichtiger als eine bessere Firmware.

W.S.

von Gabelstapler1000 (Gast)


Lesenswert?

mh schrieb:
> Was war nochmal der Grund warum du nicht gleich das richtige
> hinschreibst?

ich will den Code nicht verändern.
Ist einfacher zu debuggen. Hätte ich davor schon aufgegebn hätte ich 
jetzt überall printfx stehen.
So kann ich wenigstens printf da stehen lassen. Allerdings muss oft %ld 
anstatt %d hin :(



Rolf M. schrieb:
> Nein, denn das funktioniert nicht.

Ja muss wohl noch besser drüber nachdenken xD

von Gabelstapler1000 (Gast)


Lesenswert?

W.S. schrieb:
> Gabelstapler1000 schrieb:
>> hi ich habe in meinem code ein printf... es wird aber gar nicht
>> ausgeführt, weil der controller damit nichts anfangen kann.
>
> Hä?
> Warum hast du das dann erst in deinen Quellcode hineingeschrieben?
> Ich schätze mal, es ist gar nicht dein Quellcode, sondern irgendwas, das
> du irgendwo im Internet 'weggefunden' hast, ohne es bislang selber zu
> verstehen.
Es ist nicht mein Code. Ich möchte diesen ohne (äußerliche) Änderungen 
verwenden

Printf wird dort als Ausgabe verwendet.
Damit ich die Ausgabe sehen kann leite ich printf um xD
Allerdings wird dabei sprintf ausgeführt
%d funktioniert bei dem Controller wohl nicht für u32.

man könnte jeden Parameter von _VA_ARGS_ erst überprüfen lassen 
if(sizeof(u32var) >4 then (int)
weil der wert eh nicht mehr als 1 ist.. zumindest in dem programmteil 
den ich gesehen habe

von Oliver S. (oliverso)


Lesenswert?

Gabelstapler1000 schrieb:
> ne habe keinen STM32
> hmm also wie gesagt printf kann ich ja jetzt ersetzen mit dem Makro.
>
> Mein Problem ist nun, dass wenn ich %d angebe und eine u32 Variable habe
> eine Fehler kommt.

Ja, so ist das mit solchen völlig abstrusen Hacks. Die fallen einem 
irgendwann auf die Füße - immer.

Gabelstapler1000 schrieb:
> hi ich habe in meinem code ein printf... es wird aber gar nicht
> ausgeführt, weil der controller damit nichts anfangen kann.

Anscheinend hat deine libc ja ein printf, sonst würde der Code nicht 
linken, und du könntest den gar nicht ausführen.
Dieses printf musst du nur dazu bringen, etwas zu tun.
Warum machst du das nicht einfach?

Oliver

von Dirk B. (dirkb2)


Lesenswert?

Gabelstapler1000 schrieb:
> Also %d, uint32_t passt einfach nicht für die Zielplattform. Da gab es
> noch so was mit %x.

%d ist für die Dezimaldarstellung einer int-Variable,
%x ist für die Hexadezimaldarstellung einer int-Variable.

Das ändert nur das Aussehen, nicht die Größe (sizeof) der Variablen.

von Dirk B. (dirkb2)


Lesenswert?

Gabelstapler1000 schrieb:
> Mein Problem ist nun, dass wenn ich %d angebe und eine u32 Variable habe
> eine Fehler kommt.

Der Autor von der Bibliothek geht offenbar davon aus, dass ein int 
32-Bit hat.
Auf deinem System ist das aber nicht so.

Das kann noch ganz andere Nebenwirkungen haben, z.B. ein kleinerer 
Wertebereich, was bei Berechnungen problematisch werden kann.

Du wirst den Code ändern müssen - der Compiler hilft dir mit den 
Warnungen (den Warnlevel auf hoch einstellen).
Nimm die alle ernst.

von Johannes S. (Gast)


Lesenswert?

für die Formatierung gibt es afaik die PRIx Makros um das portabel zu 
machen.

Und printf könnte man bei gcc mit __wrap auf eigene Funktionen verbiegen 
(Linkeroption).

von Rolf M. (rmagnus)


Lesenswert?

Dirk B. schrieb:
> %x ist für die Hexadezimaldarstellung einer int-Variable.

Streng genommen für unsigned int.

von W.S. (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> Printf wird dort als Ausgabe verwendet.
> Damit ich die Ausgabe sehen kann leite ich printf um xD
> Allerdings wird dabei sprintf ausgeführt
> %d funktioniert bei dem Controller wohl nicht für u32.

Du schreibst unverständlich. Also, wenn printf 'als Ausgabe' verwendet 
wird, dann siehst du diese Ausgabe ja wohl. Oder? Was gibt es da 
umzuleiten? Und wozu sonst wäre printf gedacht? Und wo wird dabei 
sprintf ausgeführt?

Offenbar ist dein Problem nicht die Hardware oder die 
Programmiersprache, sondern verschiedene Implementationen von printf. 
Die eine will für ne Ausgabe von unsigned long ein "%d" haben und die 
andere versteht was anderes drunter ...oder garnix. Tja, wenn du partout 
bei printf bleiben willst, dann mußt du da durch. Mögliche Alternativen 
hatte ich ja schon erwähnt.

W.S.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Gabelstapler1000 schrieb:
> ne habe keinen STM32

Rück doch erstmal damit raus, was für einen µC Du verwendest. Dann 
wissen wir, ob es sich um ein 8-Bit oder 32-Bit-System handelt. Offenbar 
verwendest Du einen Source, der wg. 8 vs. 32 Bit mit Deinem Prozessor 
nicht kompatibel ist. Von daher wäre es ebenso zweckdienlich, wenn Du 
auch sagst, um welchen Source es sich handelt. Ein Link darauf wäre 
hilfreich - wenn er öffentlich zugänglich ist.

Ohne diese Infos wird das ein Stochern im Nebel.

von (prx) A. K. (prx)


Lesenswert?

Das ist jetzt schon eine ziemlich lange Salami, aber immer noch ist 
einiges fürs Scheibchen abschneiden übrig.

von Gabelstapler1000 (Gast)


Lesenswert?

Oliver S. schrieb:
> Ja, so ist das mit solchen völlig abstrusen Hacks. Die fallen einem
> irgendwann auf die Füße - immer.

Hier muss es eine Ausnahme geben.

Oliver S. schrieb:
> Dieses printf musst du nur dazu bringen, etwas zu tun.
> Warum machst du das nicht einfach?

Weil ich nicht weiß wie ich das am Besten machen kann. Habe auch noch 
nicht geschaut woher printf kommt.

Dirk B. schrieb:
> Das kann noch ganz andere Nebenwirkungen haben, z.B. ein kleinerer
> Wertebereich, was bei Berechnungen problematisch werden kann

Stimmt! Habe ich fast ignoriert.

W.S. schrieb:
> Also, wenn printf 'als Ausgabe' verwendet
> wird, dann siehst du diese Ausgabe ja wohl. Oder?
Nein kann ich nicht sehen. Also in keiner Konsole.

W.S. schrieb:
> verschiedene Implementationen von printf.
oh ich dachte es gibt nur eine von stdio.h. Das ist schlecht gemacht.

Rolf M. schrieb:
> Dirk B. schrieb:
>> %x ist für die Hexadezimaldarstellung einer int-Variable.
>
> Streng genommen für unsigned int.
Ich frage mich gerade ob das genormt ist. Aber es wird wohl ein Abkommen 
geben.

Frank M. schrieb:
> ob es sich um ein 8-Bit oder 32-Bit-System handelt
ARM Cortex M3
Reicht das als Angabe?

Johannes S. schrieb:
> für die Formatierung gibt es afaik die PRIx Makros um das portabel zu
> machen.
>
> Und printf könnte man bei gcc mit __wrap auf eigene Funktionen verbiegen
> (Linkeroption).

ok danke schaue ich mir an.

von Gabelstapler1000 (Gast)


Lesenswert?

ISO/IEC 9899:1999
..



> für die Formatierung gibt es afaik die PRIx Makros um das portabel zu


ob die wohl was bringen

von Oliver S. (oliverso)


Lesenswert?

Gabelstapler1000 schrieb:
> Weil ich nicht weiß wie ich das am Besten machen kann. Habe auch noch
> nicht geschaut woher printf kommt.

Ja, lieber einen völlig irrsinigen Hack, den du in keinster Weise 
verstehst, als mal einfach mal die Hausaufgaben machen. Die Lösung, wie 
das mit dem printf geht, steht zwar schon hier im Thread, aber trotzdem 
nochmals die schon hunderfach gestellte Frage:

Welchen Prozessor, welchen Compiler, welche toolchain, welche IDE 
verwendest du?
Wo soll dein funktionierendes printf seine Daten ausgeben: UART, LCD, 
Ethernet, SPI, ... ?

Oliver

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Gabelstapler1000 schrieb:
> ARM Cortex M3
> Reicht das als Angabe?

Nein. Was sollen diese Nebelkerzen?

Ein ARM Cortex M3 ist normalerweise ein 32-Bit-System. Das printf sollte 
mit %d und einem Integer, welcher 32 Bit groß ist, perfekt 
zurechtkommen.

Das tut es aber Deiner Aussage nach nicht. Damit passt Deine 
Entwicklungsumgebung nicht zum Reset der Geschichte. Entweder hast du 
den falschen µC in der IDE eingestellt oder Deine IDE/Tolchanin passt 
nicht zum Prozessor.

Um das festzustellen, brauchen wir von Dir präzise Antworten. Sonst 
wirst Du hier auch keine Lösung erhalten.

Also Butter bei die Fische. Sonst kommen wir hier nicht weiter.

von Dirk B. (dirkb2)


Lesenswert?

Gabelstapler1000 schrieb:
> Rolf M. schrieb:
>> Dirk B. schrieb:
>>> %x ist für die Hexadezimaldarstellung einer int-Variable.
>>
>> Streng genommen für unsigned int.
> Ich frage mich gerade ob das genormt ist. Aber es wird wohl ein Abkommen
> geben.

Ja, C und die Standard Library sind von der ISO genormt.
Die werden im Allgemeinen nach dem Erscheinungsjahr benannt. 
C89,(C90,C95),C99,C11,C18.

Aber gerade bei den Wertebereichen der Variablentypen läßt C viele 
Freiheiten.

von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> Gabelstapler1000 schrieb:
>> ARM Cortex M3
>> Reicht das als Angabe?
>
> Nein. Was sollen diese Nebelkerzen?
>
> Ein ARM Cortex M3 ist normalerweise ein 32-Bit-System. Das printf sollte
> mit %d und einem Integer, welcher 32 Bit groß ist, perfekt
> zurechtkommen.

Kommt drauf an. %d ist eben für int. Ein Compiler kann durchaus warnen, 
wenn man dem einen long statt einen int gibt, auch wenn die gleich groß 
sind. GCC tut das auch. Es ist ja streng genommen trotzdem der falsche 
Typ. Wenn man jetzt noch mit -Werror compiliert, dann bricht er dort 
auch tatsächlich mit Fehler ab.

Gabelstapler1000 schrieb:
> Oliver S. schrieb:
>> Ja, so ist das mit solchen völlig abstrusen Hacks. Die fallen einem
>> irgendwann auf die Füße - immer.
>
> Hier muss es eine Ausnahme geben.

Das unterscheidet den erfahrenen vom unerfahrenen Programmierer: 
Ersterer hat am eigenen Leib erfahren, dass es die nicht gibt.

von Gabelstapler1000 (Gast)


Lesenswert?

Frank M. schrieb:
> Entweder hast du
> den falschen µC in der IDE eingestellt oder Deine IDE/Tolchanin passt
> nicht zum Prozessor.

Oliver S. schrieb:
> Welchen Prozessor, welchen Compiler, welche toolchain, welche IDE
> verwendest du?
> Wo soll dein funktionierendes printf seine Daten ausgeben: UART, LCD,
> Ethernet, SPI, ... ?

Prozessor:https://www.microsemi.com/product-directory/soc-fpgas/1692-smartfusion2#overview
ARM M3

arm-none-eabi-gcc

ide ist vsc

muss noch weiter schauen
printf über UART wäre in Ordnung

Rolf M. schrieb:
> Ein Compiler kann durchaus warnen,
> wenn man dem einen long statt einen int gibt, auch wenn die gleich groß
> sind.

von Johannes S. (Gast)


Lesenswert?

dann wäre das Verfolgen der 1. Antwort wohl der Weg, zum printf 
redirecting gibt es viele Antworten im Netz, z.B.:
https://gist.github.com/mnemocron/46e0466637a6610026edb4e915c53e2e

von Oliver S. (oliverso)


Lesenswert?

Gabelstapler1000 schrieb:
> arm-none-eabi-gcc
>
> ide ist vsc
>
> muss noch weiter schauen
> printf über UART wäre in Ordnung

Da wird dann eine newlib oder newlib nano als standard lib drinstecken.
Vielleicht hilft dir das hier dann weiter:

https://stackoverflow.com/questions/55014043/how-do-you-implement-printf-in-gcc-from-newlib

Oliver

von W.S. (Gast)


Lesenswert?

Gabelstapler1000 schrieb:
> W.S. schrieb:
>> verschiedene Implementationen von printf.
> oh ich dachte es gibt nur eine von stdio.h. Das ist schlecht gemacht.

Ähem...
Naja, es ist durchaus nicht gut gemacht, wenn irgend eine Implementation 
von den übrigen abweicht, aber für manche Plattformen muß man eben 
Kompromisse eingehen. Deshalb sowas wie Small-C oder das ziemlich 
kommentarlose Umsetzen von double nach single bei den AVR oder eben 
reduzierte Versionen von printf zwecks Speichersparen usw.

Bei alldem ist es eben oftmals notwendig, für verschiedene 
Zielplattformen auch verschiedene Quelldateien vorzuhalten. Aber genau 
DAS scheinst du ja partout vermeiden zu wollen.

Aber bedenke mal, daß all diese Beiwerk-Funktionen, Headerdateien und 
dergleichen nix zu tun haben mit dem eigentlichen Compiler und dem 
Sprachumfang der verwendeten Programmiersprache. Das sind zwei 
verschiedene Dinge und sowas wie Bibliotheksfunktionen für printf, 
str... und so weiter kannst du vom Prinzip her dir selber schreiben nach 
deinem Gusto. Eben deshalb kannst du auch deine gesamten Textausgaben 
völlig anders organisieren als nur mittels sowas wie printf. Es ist nur 
die Frage, ob du das auch willst.

Was du allerdings immer tun mußt, ist die eigentliche Ausgabe der 
erzeugten Text-Daten auf irgend einem Medium/Kanal wie z.B. UART oder 
Display oder so, also der zugehörige Lowlevel. Wenn du (wie du weiter 
oben schriebest) deine Ausgaben nicht sehen kannst, dann wird es 
vermutlich an dieser Stelle hapern. Bevor du dich also mit printf 
herumärgerst, bringe erstmal diese Lowlevel-Dinge zum zuverlässigen 
Laufen und dann sehen wir weiter.

W.S.

von Johannes S. (Gast)


Lesenswert?

W.S. schrieb:
> Es ist nur
> die Frage, ob du das auch willst.

Der TO will eine Library verwenden die wiederum printf verwendet. Und 
die Library soll nicht modifiziert werden, was ist daran so schwer zu 
verstehen?
Das man eine Library z.B. per git vom Server klont und dann nicht 
verändern will ist absolut gängige Praxis in professioneller 
Entwicklung. So macht man das und nicht anders.

von demo (Gast)


Lesenswert?

Johannes S. schrieb:
> Der TO will eine Library verwenden die wiederum printf verwendet. Und
> die Library soll nicht modifiziert werden, was ist daran so schwer zu
> verstehen?
> Das man eine Library z.B. per git vom Server klont und dann nicht
> verändern will ist absolut gängige Praxis in professioneller
> Entwicklung. So macht man das und nicht anders.

Das ist aber auch eine gewagte These.

Fakt ist, die Fehlermeldung bringt der Compiler weil er eine Function 
mit dem Standard-Style von printf auf die Argumente abklopft. Anders als 
bei normalen Funktionen haben wir es bei printf und scanf mit variablen 
Argumentlisten zu tun und damit kann man diese Überprüfung nicht an Hand 
der Header machen. Da das aber immer wieder einen großen Teil der Fehler 
ausmacht, hat man sich halt diese Erweiterung der Compiler ausgedacht 
die variable Argumentlisten an Hand von Styles überprüfen. Bei printf 
z.B.
1
int printf, (const char *__restrict, ...) (__attribute__((__format__(__printf__, 1, 2))));

https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html

Das hat mit der realen Implementation von printf nichts zu tun. Wenn 
hier der Compiler meckert bei einem %d und 32bit sollte wohl zuerst 
überprüft werden, ob das überhaupt der richtige ist. gcc heißen sie oft, 
aber einen der was anderes als 32bit für int auf einem M3 benutzt würde 
ich als sehr verdächtig einstufen.

von Johannes S. (Gast)


Lesenswert?

für die Argumente gibt es Makros, die machen den Formatstring aber 
unleserlich und ich verwende die nur wenn unbedingt nötig, das wäre aber 
mein Problem.
https://en.cppreference.com/w/c/types/integer
Hatte ich schon erwähnt. Nur soll der printf Aufruf nicht verändert 
werden, da müsste man den Autor der Lib versuchen zu überzeugen das zu 
benutzen.

demo schrieb:
> Das ist aber auch eine gewagte These.

was ist daran gewagt? Wenn man eine Lib benutzt und die als printf 
Verweigerer umbaut, dann kann man das machen, ist aber Scheisse. Denn 
damit koppelt man sich von der Weiterentwicklung der Lib ab. Man müsste 
bei jeder neuen Version der Lib seine persönlichen Änderungen wieder 
einbringen, einen eigenen Fork pflegen, oder versuchen die Verbesserung 
als PR/MR in den master zu bekommen.
Und da es genug Möglichkeiten gibt, eine Funktion beim Linken 
umzubiegen, ist das alles nicht nötig.

von demo (Gast)


Lesenswert?

Johannes S. schrieb:
> was ist daran gewagt?

Dass man nur ein professioneller Entwickler ist wenn man sich Libs von 
github klont.

Ich bin froh über jede Lib die ich nicht von github brauche. Wenn ich 
nur mal an OneWire, RFM12-95 oder unsäglich viele andere Sensoren denke, 
dann wird mir schlecht von dem was da abgeht. Meistens ist es nur ein 
Abtippen von gefühlten Millionen defines aus dem Datenblatt und ein paar 
10 Zeiler. Da kann man mal drin Schnuppern, aber so was in ein 
Seriengerät zu verbauen hat nichts mehr mit professioneller Entwicklung 
zu tun.
Ok, das ist zwar das Forum PC-Programmierung aber es geht um Cortex-M3.
Klar gibt es auf der PC und Linux Seite genügend ernst zu nehmende Libs 
die sich über viele Jahre etabliert habe. Allerdings kenne ich keine 
einzige die  "printf" zu logging Zwecken benutzt.
Dann schon lieber "log4J". (duck und weg)

von Johannes S. (Gast)


Lesenswert?

demo schrieb:
> Dass man nur ein professioneller Entwickler ist wenn man sich Libs von
> github klont.

wer hat das wo behauptet? Auch wenn heute Freitag ist muss man nicht 
jedes Wort im Munde rumdrehen.

von Rolf M. (rmagnus)


Lesenswert?

Johannes S. schrieb:
> W.S. schrieb:
>> Es ist nur
>> die Frage, ob du das auch willst.
>
> Der TO will eine Library verwenden die wiederum printf verwendet. Und
> die Library soll nicht modifiziert werden, was ist daran so schwer zu
> verstehen?

Gegenfrage: Man kann eben eine Library, die plattformabhängig 
implementiert ist, nicht ohne Änderungen einfach auf einer anderen 
Plattform ausführen und erwarten, dass alles funktioniert. Was ist daran 
so schwer zu verstehen?

> Das man eine Library z.B. per git vom Server klont und dann nicht
> verändern will ist absolut gängige Praxis in professioneller
> Entwicklung. So macht man das und nicht anders.

Wenn das möglich ist, sollte man das machen. Es ist nur eben nicht immer 
möglich, bzw. manchmal muss man einfach zu viele Balkone dranbauen, 
damit das irgendwie trotzdem funktioniert.

von Oliver S. (oliverso)


Lesenswert?

Rolf M. schrieb:
> Gegenfrage: Man kann eben eine Library, die plattformabhängig
> implementiert ist, nicht ohne Änderungen einfach auf einer anderen
> Plattform ausführen und erwarten, dass alles funktioniert. Was ist daran
> so schwer zu verstehen?

Nun ja, wenn eine lib offenkundlich printf verwendet, wäre es schon 
sinnvoll, die auf einer Plattform eimzusetzen, die prinzipiell mit 
printf etwas anfangen kann.

Das Problem des TO ist ja auch gar nicht das printf an sich, sondern 
seine völlig Unkenntnis darüber, wie das vorhandene printf dazu gebracht 
wird, etwas über die uart auszugeben (und dazu seine völlige Unkenntnis 
über den ganze Rest dazu).

Oliver

von Rolf M. (rmagnus)


Lesenswert?

Oliver S. schrieb:
> Das Problem des TO ist ja auch gar nicht das printf an sich, sondern
> seine völlig Unkenntnis darüber, wie das vorhandene printf dazu gebracht
> wird, etwas über die uart auszugeben (und dazu seine völlige Unkenntnis
> über den ganze Rest dazu).

Dieses Problem wurde doch schon vor langem gelöst. Das verbleibende 
Problem ist, dass die Format-Specifier nicht passen. Siehe 
Beitrag "Re: printf ersetzen"

von W.S. (Gast)


Lesenswert?

Johannes S. schrieb:
> Der TO will eine Library verwenden die wiederum printf verwendet. Und
> die Library soll nicht modifiziert werden, was ist daran so schwer zu
> verstehen?

Deine Erwiderung ist nicht zu verstehen.
Wenn irgendwelche Quelldateien nicht zur aktuellen Plattform passen, 
dann passen die eben nicht. So einfach kann man das sagen. Das solltest 
du verstehen.

In solchem Falle ist eben entweder ein Neuschreiben oder ein Anpassen 
erforderlich.

W.S.

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.