Forum: Compiler & IDEs printf uint64_t mit newlib-nano


von Heiko J. (heiko_j)


Lesenswert?

Hallo,

ich hab da so ein Problem, eigentlich müsste ich mich ja dafür schämen 
das ich sowas überhaupt frag, aber ...
Versuche ich mit mit newlib-nano und printf ein uint64_t auszugeben 
bekomme ich nur "lu" als Ausgabe. Laut C99 sollte man ja das PRIu64 
Macro verwenden, das funzt allerdings genau so wenig wie %llu. CPU ist 
ein Cortex-M3, mit der aktuellen gcc-4.7 toolchain von launchpad. Wie 
geht's denn richtig ?

#include <stdint.h>

...

uint64_t foo = 42;
fprintf(stdout, "Value %llu\r\n", foo );
fprintf(stdout, "Value %"PRIu64"\r\n", foo );

...

Das Ergebnis ist dann:
"Value lu"
"Value lu"

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

[f]printf ist Aufgabe der newlib.  Der Name "newlib-nano" läßt vermuten, 
dass diese Inkarnation der newlib nur einen abgespeckten Funktionsumfang 
mitbringt. Klarkeit schafft das Manual der newlib-nano.

von Heiko J. (heiko_j)


Lesenswert?

Johann L. schrieb:
> Klarkeit schafft das Manual der newlib-nano.
Ich würd' ja gerne RTFM machen, aber ich hab bisher absolut NULL 
brauchbare Doku zur newlib-nano gefunden.

von chris (Gast)


Lesenswert?

Soweit ich mich errinnere ist long long da nicht unterstützt.

Unsigned ist einfach, zumindest wenn einem eine führende Null nicht 
stört.
uint64_t foo = 42;
fprintf(stdout, "Value %u%u\r\n", foo>>32,(uint32_t)foo );
Für Signed braucht es eine Helper Funktion, z.B.

char* l2s(long long v) { static char buff[22]; char*s=buff;
  unsigned long l;
  if(v<0) v=-v,*s++='-'; if(h=v>>32) s+=sprintf(s,"%u",l); l=v;
  sprintf(s,"%u",l); return buff;
  }

Wenn du dann Längenbeschränkung usw brauchst, dann kannst du mit %* 
arbeiten,
und dies auch der Funktion übergeben.

von chris (Gast)


Lesenswert?

if(h=v>>32) sollte  if(l=v>>32) sein, vielleicht gibt es auch andere
Flüchtigkeitsfehler, aber eigentlich sollte das Prinzip klar sein.

von Stefan E. (sternst)


Lesenswert?

chris schrieb:
> Unsigned ist einfach, zumindest wenn einem eine führende Null nicht
> stört.
> uint64_t foo = 42;
> fprintf(stdout, "Value %u%u\r\n", foo>>32,(uint32_t)foo );
> Für Signed braucht es eine Helper Funktion, z.B.
>
> char* l2s(long long v) { static char buff[22]; char*s=buff;
>   unsigned long l;
>   if(v<0) v=-v,*s++='-'; if(h=v>>32) s+=sprintf(s,"%u",l); l=v;
>   sprintf(s,"%u",l); return buff;
>   }

Sorry, aber das ist doch Unsinn. Zur einfacheren Veranschaulichung wende 
dein Prinzip doch mal auf 16-Bit an (also mit zwei 8-Bit-Ausgaben), und 
nimm 0x1111 als Beispiel:
Was wird angezeigt? 1717
Was wäre richtig? 4369

von chris (Gast)


Angehängte Dateien:

Lesenswert?

Naja, ich benutze 0x%x%8.8x , da passt es.
Keine Ahnung was mich da geritten hat.
Deswegen hier die korrigierte Funktion.

von Peter D. (peda)


Lesenswert?

Interessehalber wüßte ich doch gerne, wozu ein Mensch 20-stellige 
Zahlenmonster ablesen will.

Für Datenübertragung würde ich Hex vorziehen, damit kann man beliebig 
lange Byte-Ströme einfach übertragen.

von Heiko J. (heiko_j)


Lesenswert?

Peter Dannegger schrieb:
> Interessehalber wüßte ich doch gerne, wozu ein Mensch 20-stellige
> Zahlenmonster ablesen will.

Damit ich sie zu debugging Zwecken mit anderen 20-stelligen 
Zahlenmonstern vergleichen kann.

> Für Datenübertragung würde ich Hex vorziehen, damit kann man beliebig
> lange Byte-Ströme einfach übertragen.
Mir wär Hex ja auch lieber, aber
a) Kann ich im Quellsystem das es anzubinden gilt auch nur dezimal 
ablesen.
b) Trifft das Problem auch auf llx zu.

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

newlib-nano wurde von den Leuten von ARM als Erweiterung der newlib von 
Redhat entwickelt, die auch die
'GNU Tools for ARM Embedded Processors' auf launchpad.net mit dieser 
Laufzeitbibliothek bereitstellen. Fragen dazu also am besten dort 
stellen. Wurde allerdings schon gefragt und beantwortet:
https://answers.launchpad.net/gcc-arm-embedded/+question/219065 und
https://answers.launchpad.net/gcc-arm-embedded/+question/220287
Ja, Dokumentation der Änderungen für newlib-nano ist noch dürftig aber 
im Quellcode der newlib-nano kann man die (Nicht-)Funktionalität 
nachvollziehen. Quellcode als Archiv auf launchpad und zum Durchklicken 
auf github (github evtl. nicht aktuell, habe die aktuellen Quellen 
bisher nicht 'gedifft').

Was spricht dagegen, die absoluten Werte als Päckchen aus hex-Zahlen 
(dead:beef:cafe:babe) gegenüberzustellen (Differenzen evtl. dann dezimal 
nach Fallunterscheidung) oder, da es zu "debugging Zwecken" ist, mit der 
unmodifizierten newlib zu arbeiten? Falls erforderlich, bei den Tests 
mit einem Controller der gleichen Baureihe aber mehr Speicher.

von Heiko J. (heiko_j)


Lesenswert?

Martin Thomas schrieb:
> Was spricht dagegen, die absoluten Werte als Päckchen aus hex-Zahlen
> (dead:beef:cafe:babe) gegenüberzustellen (Differenzen evtl. dann dezimal
> nach Fallunterscheidung)
Wie schon gesagt, am Quellsystem wo die Daten her kommen seh ich das 
ganze nur als Dezimalwert im Display und im Zielsystem wo ich mein 
Progrämmschen laufen hab kann ich sie nicht als Dezimalwert ausgeben. 
Einen von beiden Werten muss ich wohl händisch umrechnen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Und was hält dich davon ab, ne eigne, kleine Routine für die Wandlung 
zum ASCII-Format der Dezimaldarstellung zu schreiben?

Der Code ist so einfach, daß es fast peinlich ist, den hier zu posten...

von Heiko J. (heiko_j)


Lesenswert?

Johann L. schrieb:
> Und was hält dich davon ab, ne eigne, kleine Routine für die Wandlung
> zum ASCII-Format der Dezimaldarstellung zu schreiben?
Davon hält mich nur ab, das ich das Problem mittlerweile anderweitig 
(Von Hand umrechnen) gelöst habe.

> Der Code ist so einfach, daß es fast peinlich ist, den hier zu posten...
Du meinst sowas wie weiter oben schon gepostet wurde ?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Heiko Jakob schrieb:
> Johann L. schrieb:
>> Der Code ist so einfach, daß es fast peinlich ist, den hier zu posten...
> Du meinst sowas wie weiter oben schon gepostet wurde ?

Was oben steht würde ich schwerlich als Code bezeichnen wollen.
1
#include <stdint.h>
2
#include <stdio.h>
3
#include <string.h>
4
5
void dump_u64 (uint64_t x)
6
{
7
    char buf[21 /* = [2 + 64 * ln 2 / ln 10] */], *b = buf;
8
9
    do
10
    {
11
        *b++ = '0' + (x % 10);
12
        x /= 10;
13
    } while (x);
14
15
    *b++ = '\0';
16
    
17
    puts (strrev (buf));
18
}

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.