Wie formatiere ich ein unsigned long long int mit printf?

379
#include <stdio.h>
int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Ausgabe:

My number is 8 bytes wide and its value is 285212672l. A normal number is 0.

Ich gehe davon aus, dass dieses unerwartete Ergebnis vom Drucken der stammt unsigned long long int. Wie wollen Sie printf()Benutzer unsigned long long int?

andrewrk
quelle
2
Ich habe gerade Ihren Code (mit% llu) mit gcc kompiliert und die Ausgabe war die richtige. Übergeben Sie Optionen an den Compiler?
Juan
2
Beachten Sie, dass Samsung Badas Newlib "% lld" nicht zu unterstützen scheint: developer.bada.com/forum/…
RzR
Ich würde vorschlagen, stdint.h zu verwenden und die Anzahl der Bits in Ihrer Variablen explizit anzugeben. Wir befinden uns immer noch in einer Übergangsphase zwischen 32- und 64-Bit-Architekturen, und "unsigned long long int" bedeutet nicht für beide dasselbe.
BD in Rivenhill

Antworten:

483

Verwenden Sie den Long-Long-Modifikator ll (el-el) mit der u-Konvertierung (ohne Vorzeichen). (Funktioniert in Windows, GNU).

printf("%llu", 285212672);
John Downey
quelle
11
Genauer gesagt ist es für GNU libc und funktioniert nicht mit der C-Laufzeit von Microsoft.
Mark Baker
168
Dies ist keine Linux / UNIX-Sache. Der Längenmodifikator "ll" wurde in C99 zu Standard C hinzugefügt. Wenn er in "Microsoft C" nicht funktioniert, liegt dies daran, dass sie nicht standardkonform sind.
Robert Gamble
12
Funktioniert für mich in VS2008. Soweit ich mich erinnere, soll der MS C-Compiler (wenn er zum Kompilieren von Straight C eingerichtet ist) vom Design her C90-konform sein. C99 führte einige Dinge ein, die nicht allen gefallen haben.
ン ー パ ー フ ァ ミ ミ ン
6
Eine Sache, die Sie hier beachten sollten, ist, dass, wenn Sie mehrere long longArgumente an eines von ihnen übergeben printfund das falsche Format für eines von ihnen verwenden, beispielsweise %danstelle von %lld, selbst die Argumente, die nach dem falschen gedruckt werden, möglicherweise vollständig deaktiviert sind (oder sogar printfzum Absturz führen können ). Im Wesentlichen werden variable Argumente ohne Typinformationen an printf übergeben. Wenn also die Formatzeichenfolge falsch ist, ist das Ergebnis unvorhersehbar.
Dmitrii
1
In einem Interview sagte Herb Sutter, dass die Kunden von Microsoft nicht nach C99 fragen, sodass ihr reiner C-Compiler bei C90 eingefroren wurde. Dies gilt, wenn Sie als C kompilieren. Wenn Sie als C ++ kompilieren, wie andere oben angegeben haben, sollte es Ihnen gut gehen.
Ahcox
90

Möglicherweise möchten Sie mit der inttypes.h Bibliothek , um zu versuchen , die Sie Typen wie gibt int32_t, int64_t, uint64_tetc. Sie können dann ihre Makros verwenden wie zum Beispiel:

uint64_t x;
uint32_t y;

printf("x: %"PRId64", y: %"PRId32"\n", x, y);

Dies wird als „garantiert“ nicht geben Ihnen die gleichen Probleme wie long, unsigned long longetc, da Sie nicht erraten, wie viele Bits in jedem Datentyp sind.

Nathan Fellman
quelle
wo diese PRId64, PRId32definiert Makros?
happy_marmoset
4
@happy_marmoset: Sie sind definiert ininttypes.h
Nathan Fellman
4
Ich denke, Sie brauchen PRIu64und PRIu32für vorzeichenlose ganze Zahlen.
Lasse Kliemann
1
Ist inttypes.hStandard? Wäre es nicht so stdint.h?
MD XF
2
Beachten Sie, dass diese Typen mit exakter Breite optional sind , da es Architekturen gibt, die keine ganzzahligen Typen mit diesen exakten Breiten haben. Nur die Typen leastXund fastX(die tatsächlich breiter als angegeben sein können) sind obligatorisch.
DevSolar
78

%d-> für int

%u-> für unsigned int

%ld-> für long intoderlong

%lu-> für unsigned long intoder long unsigned intoderunsigned long

%lld-> für long long intoderlong long

%llu-> für unsigned long long intoderunsigned long long

Shivam Chauhan
quelle
Gibt es einen Formatbezeichner wie die Anzahl der anzuzeigenden Stellen, die linke oder rechte Ausrichtung für% lld oder% llu?
Asam Padeh
40

Für lange lange (oder __int64) mit MSVS sollten Sie% I64d verwenden:

__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b);    //I is capital i

quelle
37

Dies liegt daran, dass% llu unter Windows nicht ordnungsgemäß funktioniert und% d keine 64-Bit-Ganzzahlen verarbeiten kann. Ich schlage vor, stattdessen PRIu64 zu verwenden, und Sie werden feststellen, dass es auch auf Linux portierbar ist.

Versuchen Sie stattdessen Folgendes:

#include <stdio.h>
#include <inttypes.h>

int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    /* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
    printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Ausgabe

My number is 8 bytes wide and its value is 285212672. A normal number is 5.
Paul Hargreaves
quelle
+1 für den Verweis auf PRIu64, den ich noch nie gesehen hatte, aber dies scheint (zumindest) nicht auf 64-Bit-Linux portierbar zu sein, da PRIu64 auf "lu" anstelle von "llu" erweitert wird.
BD in Rivenhill
8
Und warum sollte das schlecht sein? Ein Long ist ein 64-Bit-Wert unter 64-Bit-Linux, wie auf jedem anderen Betriebssystem außer Windows.
Ringding
@ BDatRivenhill Linux / Unix verwendet LP64, in dem 64 Bit lang sind
phuclv
1
Um es jedoch portabler zu machen, verwenden Sie es int64_tstattdessen, da es möglicherweise einige Implementierungen gibt, bei denen long long größer als long ist
phuclv
das sollte nach oben! - ein kleines Update: Fehler: ungültiges Suffix im Literal; C ++ 11 erfordert ein Leerzeichen zwischen Literal und Bezeichner [-Werverved-user-defined-literal]
tofutim
14

Unter Linux ist es %lluund unter Windows ist es%I64u

Obwohl ich festgestellt habe, dass es in Windows 2000 nicht funktioniert, scheint es dort einen Fehler zu geben!

Adam Pierce
quelle
Mit Windows (oder zumindest mit dem Microsoft C-Compiler für Windows) gibt es auch% I64d,% I32u und% I32d
JustJeff
1
Was hat das mit Windows 2000 zu tun? Die C-Bibliothek ist diejenige, die printf verarbeitet.
CMircea
1
Genau das, was ich beobachtet habe. Ich habe eine App geschrieben, die dieses Konstrukt verwendet und unter WinXP perfekt funktioniert, aber unter Win2k Müll gespuckt hat. Vielleicht hat es etwas mit einem Systemaufruf zu tun, den die C-Bibliothek an den Kernel sendet, vielleicht hat es etwas mit Unicode zu tun, wer weiß. Ich erinnere mich, dass ich es mit _i64tot () oder so etwas umgehen musste.
Adam Pierce
7
Klingt so, als würde MS seine "Freiheit zur Innovation" wieder
ausüben
Das Win2k / Win9x-Problem ist wahrscheinlich darauf zurückzuführen, dass der unsigned long longDatentyp (zu der Zeit mit dem C99-Standard) relativ neu ist, C-Compiler (einschließlich MinGW / GCC) jedoch die alte Microsoft C-Laufzeit verwenden, die nur die C89-Spezifikation unterstützt. Ich habe nur Zugriff auf wirklich alte und relativ aktuelle Windows-API-Dokumente. Es ist daher schwierig, genau zu sagen, wann der I64uSupport eingestellt wurde. Aber es klingt wie in der XP-Ära.
veganaiZe
8

Kompilieren Sie es als x64 mit VS2005:

% llu funktioniert gut.

Sandig
quelle
3

Zusätzlich zu dem, was die Leute vor Jahren geschrieben haben:

  • Möglicherweise wird dieser Fehler bei gcc / mingw angezeigt:

main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]

printf("%llu\n", k);

Dann ist Ihre Version von mingw nicht standardmäßig c99. Fügen Sie dieses Compiler-Flag hinzu : -std=c99.

Bernd Elkemann
quelle
3

Anscheinend hat sich seit über einem Jahrzehnt niemand eine Multi-Plattform * -Lösung ausgedacht seit [dem] Jahr 2008 seit ausgedacht, also werde ich meine anhängen 😛. Bitte stimmen Sie zu. (Scherz. Es ist mir egal.)

Lösung: lltoa()

Wie benutzt man:

#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));

OPs Beispiel:

#include <stdio.h>
#include <stdlib.h> /* lltoa() */

int main() {
    unsigned long long int num = 285212672; // fits in 29 bits
    char dummy[255];
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %s. "
        "A normal number is %d.\n", 
        sizeof(num), lltoa(num, dummy, 10), normalInt);
    return 0;
}

Im Gegensatz zur %lldDruckformatzeichenfolge funktioniert diese für mich unter 32-Bit-GCC unter Windows.

*) Nun, fast plattformübergreifend. In MSVC brauchen Sie anscheinend _ui64toa()statt lltoa().

7vujy0f0hy
quelle
1
Ich habe keine lltoa.
Antti Haapala
1

Nicht standardmäßige Dinge sind immer seltsam :)

für den langen langen Teil unter GNU ist es L, lloderq

und unter Fenstern glaube ich, dass es llnur ist

funkelt
quelle
1

Verhexen:

printf("64bit: %llp", 0xffffffffffffffff);

Ausgabe:

64bit: FFFFFFFFFFFFFFFF
lama12345
quelle
Sehr schön! Ich fragte mich, wie ich es in
hexadezimaler
Fast alle C ++ - und C-Compiler geben jedoch die Warnung aus: Warnung: Verwendung des Längenmodifikators 'll' mit dem Typzeichen 'p' [-Wformat =]
Seshadri R
2
Diese völlig gebrochene Antwort hat ein doppelt undefiniertes Verhalten und beginnt nicht einmal, die Frage zu beantworten .
Antti Haapala
@AnttiHaapala Sie sagen, diese Antwort ist völlig gebrochen mit doppelt undefiniertem Verhalten. Können Sie das näher erläutern oder soll ich sie einfach löschen? Oder als gutes schlechtes Beispiel behalten?
lama12345
0

Eine Möglichkeit besteht darin, es mit VS2008 als x64 zu kompilieren

Dies läuft wie erwartet:

int normalInt = 5; 
unsigned long long int num=285212672;
printf(
    "My number is %d bytes wide and its value is %ul. 
    A normal number is %d \n", 
    sizeof(num), 
    num, 
    normalInt);

Für 32-Bit-Code müssen wir den korrekten __int64-Formatbezeichner% I64u verwenden. So wird es.

int normalInt = 5; 
unsigned __int64 num=285212672;
printf(
    "My number is %d bytes wide and its value is %I64u. 
    A normal number is %d", 
    sizeof(num),
    num, normalInt);

Dieser Code funktioniert sowohl für 32- als auch für 64-Bit-VS-Compiler.

vzczc
quelle
Versuchen Sie es mit einer tatsächlichen 64-Bit-Nummer anstelle von '285212672', und ich glaube nicht, dass das erste Beispiel korrekt ausgeführt und für ein beliebiges Ziel kompiliert wurde.
Dyasta